home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / game / misc / mris1_1src.lha / .mris1_1src.lha / main.c < prev    next >
C/C++ Source or Header  |  1996-10-16  |  84KB  |  3,550 lines

  1. #ifndef DEVICES_GAMEPORT_H
  2. #include <devices/gameport.h>
  3. #endif
  4.  
  5. #ifndef PREFS_PREFHDR_H
  6. #include <prefs/prefhdr.h>
  7. #endif
  8.  
  9. #ifndef DOS_EXALL_H
  10. #include <dos/exall.h>
  11. #endif
  12.  
  13. #ifndef WORKBENCH_STARTUP_H
  14. #include <workbench/startup.h>
  15. #endif
  16.  
  17. #ifndef INTUITION_IMAGECLASS_H
  18. #include <intuition/imageclass.h>
  19. #endif
  20.  
  21. #ifndef GRAPHICS_VIDEOCONTROL_H
  22. #include <graphics/videocontrol.h>
  23. #endif
  24.  
  25. #include <proto/locale.h>
  26. #include <proto/layers.h>
  27. #include <proto/commodities.h>
  28. #include <proto/gadtools.h>
  29. #include <proto/diskfont.h>
  30. #include <proto/icon.h>
  31. #include <proto/wb.h>
  32. #include <proto/asl.h>
  33. #include <proto/utility.h>
  34.  
  35. #include "Version.h"
  36.  
  37. #define CATCOMP_BLOCK
  38.  
  39. #include "xmris.h"
  40. #include "defmris.h"
  41. #include "ConfigKeys.h"
  42. #include "ChangeUser.h"
  43. #include "Manual.h"
  44. #include "BOOPSILib.h"
  45. #include "ConfigFont.h"
  46. #include "ConfigScreen.h"
  47. #include "Errors.h"
  48.  
  49. #include "StaticSavedsAsmA1A2.h"
  50.  
  51. #include "Catalog.h"
  52.  
  53. #define JOYSTICK_TRIES        200
  54.  
  55. /************************************************************************/
  56.  
  57. const char VersionString[]=
  58.   "$VER: " PROGRAM_NAME " " PROGRAM_VERSION " (" PROGRAM_DATE ")based on Xmris " XMRISVERSION " (" DATE ")";
  59.  
  60. const ULONG StackSize=45000;
  61.  
  62. /************************************************************************/
  63.  
  64. extern struct DiskObject mrisIcon;
  65.  
  66. /************************************************************************/
  67.  
  68. struct GameSupportBase *GameSupportBase;
  69.  
  70. struct DosLibrary *DOSBase;
  71. struct GfxBase *GfxBase;
  72. struct IntuitionBase *IntuitionBase;
  73. struct Library *UtilityBase;
  74. struct Library *LocaleBase;
  75. struct Library *LayersBase;
  76. struct Library *CxBase;
  77. struct Library *GadToolsBase;
  78. struct Library *KeymapBase;
  79. struct Library *IconBase;
  80. struct Library *WorkbenchBase;
  81.  
  82. struct Locale *Locale;
  83. struct Catalog *Catalog;
  84.  
  85. struct TimeFormats Formats;
  86.  
  87. #if defined(__SASC)
  88. UWORD __chip DitherPattern[2]={0x5555,0xaaaa};
  89. #else
  90. UWORD *DitherPattern;
  91. #endif
  92.  
  93. struct MiscState MiscState;
  94.  
  95. struct MsgPort WindowPort=
  96. {
  97.   {NULL,NULL,NT_MSGPORT,0,NULL},
  98.   PA_SIGNAL,
  99.   0,
  100.   NULL,
  101.   {(struct Node *)&WindowPort.mp_MsgList.lh_Tail,NULL,(struct Node *)&WindowPort.mp_MsgList.lh_Head,NT_MESSAGE}
  102. };
  103.  
  104. struct MsgPort MiscPort=
  105. {
  106.   {NULL,NULL,NT_MSGPORT,0,NULL},
  107.   PA_SIGNAL,
  108.   0,
  109.   NULL,
  110.   {(struct Node *)&MiscPort.mp_MsgList.lh_Tail,NULL,(struct Node *)&MiscPort.mp_MsgList.lh_Head,NT_MESSAGE}
  111. };
  112.  
  113. struct TextAttr TextAttr;
  114. char *ScreenDescription;
  115.  
  116. /************************************************************************/
  117.  
  118. static char *WindowTitle;
  119. static ULONG AllocateJoystickCounter;
  120.  
  121. static struct Window *About;
  122.  
  123. static struct Window *CompileInfo;
  124. extern const char CompileDate[];
  125. extern const char CompileTime[];
  126.  
  127. static BPTR GardenDir;
  128.  
  129. static struct MsgPort WBPort=
  130. {
  131.   {NULL,NULL,NT_MSGPORT,0,NULL},
  132.   PA_SIGNAL,
  133.   SIGBREAKB_CTRL_F,
  134.   NULL,
  135.   {(struct Node *)&WBPort.mp_MsgList.lh_Tail,NULL,(struct Node *)&WBPort.mp_MsgList.lh_Head,NT_MESSAGE}
  136. };
  137.  
  138. static CxObj *Broker;
  139. static struct NewBroker NewBroker=
  140. {
  141.   NB_VERSION,
  142.   NULL,
  143.   NULL,
  144.   NULL,
  145.   NBU_UNIQUE,
  146.   COF_SHOW_HIDE,
  147.   0,
  148.   &MiscPort
  149. };
  150.  
  151. static struct AsyncAslMessage ConfigMessage;
  152.  
  153. static struct Gadget IconifyGadget=
  154. {
  155.   NULL,
  156.   0,0,0,0,
  157.   GFLG_GADGHIMAGE | GFLG_GADGIMAGE | GFLG_RELRIGHT,
  158.   GACT_RELVERIFY | GACT_TOPBORDER,
  159.   GTYP_BOOLGADGET,
  160.   NULL,
  161.   NULL,
  162.   NULL,
  163.   0,
  164.   NULL,
  165.   0,
  166.   NULL
  167. };
  168.  
  169. /************************************************************************/
  170.  
  171. static const char * const MrisToolTypes[]=
  172. {
  173.   "UP",            /* 0 */
  174.   "DOWN",        /* 1 */
  175.   "LEFT",        /* 2 */
  176.   "RIGHT",        /* 3 */
  177.   "THROW",        /* 4 */
  178.   "PAUSE",        /* 5 */
  179.   "QUIT",        /* 6 */
  180.   "ICONIZE",        /* 7 */
  181.   "RANDOM",        /* 8 */
  182.   "DYNAMIC",        /* 9 */
  183.   "USER",        /* 10 */
  184.   "PUBSCREEN",        /* 11 */
  185.   "SCREEN",        /* 12 */
  186.   "JOYSTICK",        /* 13 */
  187.   "FONT",        /* 14 */
  188.   "MSIT"        /* 15 */
  189. };
  190.  
  191. /************************************************************************/
  192.  
  193. static int ProcessMisc(void);
  194.  
  195. /************************************************************************/
  196. /*                                    */
  197. /* Compare two scores                            */
  198. /*                                    */
  199. /************************************************************************/
  200.  
  201. STATIC_SAVEDS_ASM_A1A2(ULONG,ScoreCompareCode,void *,Score2,void *,Score1)
  202.  
  203. {
  204.   LONG Diff;
  205.  
  206.   Diff=((HIGH_SCORE *)Score1)->score-((HIGH_SCORE *)Score2)->score;
  207.   if (Diff==0)
  208.     {
  209.       Diff=((HIGH_SCORE *)Score1)->screen-((HIGH_SCORE *)Score2)->screen;
  210.       if (Diff==0)
  211.     {
  212.       Diff=((HIGH_SCORE *)Score1)->elapsed-((HIGH_SCORE *)Score2)->elapsed;
  213.       if (Diff==0)
  214.         {
  215.           Diff=((HIGH_SCORE *)Score1)->Score.TimeStamp-((HIGH_SCORE *)Score2)->Score.TimeStamp;
  216.         }
  217.     }
  218.     }
  219.   return (ULONG)Diff;
  220. }
  221.  
  222. /*--------------------*/
  223.  
  224. static const struct Hook ScoreCompareHook=
  225. {
  226.   {NULL,NULL},ScoreCompareCode,NULL,NULL
  227. };
  228.  
  229. /************************************************************************/
  230.  
  231. const struct ScoreDef ScoreDef=
  232. {
  233.   {
  234.     &ScoreCompareHook,
  235.     PROGRAM_NAME,
  236.     { HIGH_SCORES, HIGH_SCORES, HIGH_SCORES },
  237.     ARRAYSIZE(ScoreDef.Chunks)
  238.   },
  239.   {
  240.     {MAKE_ID('S','C','O','R'),GS_SCOREDEFF_INTEGER,sizeof(ULONG)},
  241.     {MAKE_ID('L','E','V','L'),GS_SCOREDEFF_INTEGER,sizeof(ULONG)},
  242.     {MAKE_ID('E','L','A','P'),GS_SCOREDEFF_INTEGER,sizeof(ULONG)}
  243.   }
  244. };
  245.  
  246. /************************************************************************/
  247.  
  248. #define NM(Type,Name,Flags) {NM_##Type,(STRPTR)MSG_##Name##_MENU,NULL,Flags,0,(APTR)MSG_##Name##_MENU}
  249.  
  250. static struct NewMenu NewMenu[]=
  251. {
  252.   {NM_TITLE,(STRPTR)MSG_GAME_MENU,NULL,0,0,NULL},
  253.   NM(ITEM,GAME_USER,0),
  254.   NM(ITEM,GAME_ERRORS,0),
  255.   {NM_ITEM,NM_BARLABEL,NULL,0,0,NULL},
  256.   NM(ITEM,GAME_ABOUT,0),
  257.   {NM_ITEM,NM_BARLABEL,NULL,0,0,NULL},
  258.   NM(ITEM,GAME_QUIT,0),
  259.  
  260.   {NM_TITLE,(STRPTR)MSG_GARDENS_MENU,NULL,0,0,(APTR)MSG_GARDENS_MENU},
  261.  
  262.   {NM_TITLE,(STRPTR)MSG_DEMO_MENU,NULL,0,0,(APTR)MSG_DEMO_MENU},
  263.   NM(ITEM,DEMO_SCORES,NM_ITEMDISABLED),
  264.   NM(ITEM,DEMO_BOARD,NM_ITEMDISABLED),
  265.   NM(ITEM,DEMO_KEYS,0),
  266.   NM(ITEM,DEMO_NAME,0),
  267.   NM(ITEM,DEMO_SPRITES,0),
  268.  
  269.   {NM_TITLE,(STRPTR)MSG_CONFIG_MENU,NULL,0,0,NULL},
  270.  
  271.   NM(ITEM,CONFIG_RANDOM,CHECKIT | MENUTOGGLE),
  272.  
  273.   {NM_ITEM,(STRPTR)MSG_CONFIG_CONTROL_MENU,NULL,0,0,NULL},
  274.   NM(SUB,CONFIG_CONTROL_JOYSTICK,CHECKIT | MENUTOGGLE | CHECKED),
  275.   NM(SUB,CONFIG_CONTROL_KEYS,0),
  276.  
  277.   {NM_ITEM,(STRPTR)MSG_CONFIG_DISPLAY_MENU,NULL,0,0,NULL},
  278.   NM(SUB,CONFIG_DISPLAY_MSIT,CHECKIT | MENUTOGGLE),
  279.   NM(SUB,CONFIG_DISPLAY_DYNAMIC,CHECKIT | MENUTOGGLE | CHECKED),
  280.   NM(SUB,CONFIG_DISPLAY_SCREEN,0),
  281.   NM(SUB,CONFIG_DISPLAY_FONT,0),
  282.  
  283.   {NM_ITEM,NM_BARLABEL,NULL,0,0,NULL},
  284.   NM(ITEM,CONFIG_SAVE,0),
  285.   NM(ITEM,CONFIG_SAVEDEFAULT,0),
  286.  
  287.   {NM_END}
  288. };
  289.  
  290. struct StringNode
  291. {
  292.   struct StringNode *Next;
  293. };
  294.  
  295. static struct StringNode *GardenStrings;
  296.  
  297. /************************************************************************/
  298. /*                                    */
  299. /*                                    */
  300. /************************************************************************/
  301.  
  302. void FreeBOOPSIClasses(void)
  303.  
  304. {
  305.   if (FreeClass(BOOPSILibC_Root))
  306.     {
  307.       BOOPSILibC_Root=NULL;
  308.     }
  309.   if (FreeClass(BOOPSILibC_Group))
  310.     {
  311.       BOOPSILibC_Group=NULL;
  312.     }
  313.   if (FreeClass(BOOPSILibC_String))
  314.     {
  315.       BOOPSILibC_String=NULL;
  316.     }
  317.   if (FreeClass(BOOPSILibC_Button))
  318.     {
  319.       BOOPSILibC_Button=NULL;
  320.     }
  321.   if (FreeClass(BOOPSILibC_Label))
  322.     {
  323.       BOOPSILibC_Label=NULL;
  324.     }
  325.   if (FreeClass(BOOPSILibC_Frame))
  326.     {
  327.       BOOPSILibC_Frame=NULL;
  328.     }
  329. }
  330.  
  331. /************************************************************************/
  332.  
  333. int CreateBOOPSIClasses(void)
  334.  
  335. {
  336.   if (BOOPSILibC_Group!=NULL || CreateBOOPSILibC_Group()!=NULL)
  337.     {
  338.       if (BOOPSILibC_String!=NULL || CreateBOOPSILibC_String()!=NULL)
  339.     {
  340.       if (BOOPSILibC_Button!=NULL || CreateBOOPSILibC_Button()!=NULL)
  341.         {
  342.           if (BOOPSILibC_Label!=NULL || CreateBOOPSILibC_Label()!=NULL)
  343.         {
  344.           if (BOOPSILibC_Frame!=NULL || CreateBOOPSILibC_Frame()!=NULL)
  345.             {
  346.               if (BOOPSILibC_Root!=NULL || CreateBOOPSILibC_Root()!=NULL)
  347.             {
  348.               return TRUE;
  349.             }
  350.             }
  351.         }
  352.         }
  353.     }
  354.     }
  355.   FreeBOOPSIClasses();
  356.   return FALSE;
  357. }
  358.  
  359. /************************************************************************/
  360. /*                                    */
  361. /* Delete a Pixmap                            */
  362. /*                                    */
  363. /************************************************************************/
  364.  
  365. static void DeletePixmap(Pixmap *Data)
  366.  
  367. {
  368.   if (Data->Layer!=NULL)
  369.     {
  370.       while (!DeleteLayer(0,Data->Layer))
  371.     {
  372.       Delay(TICKS_PER_SECOND);    /* anyone with a better idea? */
  373.     }
  374.       Data->Layer=NULL;
  375.     }
  376.   if (Data->LayerInfo!=NULL)
  377.     {
  378.       DisposeLayerInfo(Data->LayerInfo);
  379.       Data->LayerInfo=NULL;
  380.     }
  381.   WaitBlit();
  382.   FreeBitMap(Data->BitMap);
  383.   Data->BitMap=NULL;
  384. }
  385.  
  386. /************************************************************************/
  387. /*                                    */
  388. /* Delete our offscreen bitmaps                        */
  389. /*                                    */
  390. /************************************************************************/
  391.  
  392. static void FreeBitmaps(void)
  393.  
  394. {
  395.   int i;
  396.  
  397.   DeletePixmap(&display.copy);
  398.   DeletePixmap(&display.back);
  399.   for (i=0; i<BOARD_SCORES; i++)
  400.     {
  401.       DeletePixmap(&update.score.list[i].image);
  402.       DeletePixmap(&update.score.list[i].mask);
  403.     }
  404. }
  405.  
  406. /************************************************************************/
  407. /*                                    */
  408. /*                                    */
  409. /************************************************************************/
  410.  
  411. static void FreeJoystick(void)
  412.  
  413. {
  414.   if (MiscState.Joystick)
  415.     {
  416.       MiscState.Joystick=FALSE;
  417.       AbortIO(&GameSupportBase->Joystick.Request);
  418.       WaitIO(&GameSupportBase->Joystick.Request);
  419.       GS_FreeJoystick();
  420.     }
  421.   AllocateJoystickCounter=0;
  422. }
  423.  
  424. /************************************************************************/
  425. /*                                    */
  426. /* Free dynamic colors                            */
  427. /*                                    */
  428. /************************************************************************/
  429.  
  430. static void ReleaseDynamic(void)
  431.  
  432. {
  433.   if (display.dynamic)
  434.     {
  435.       struct ColorMap *ColorMap;
  436.  
  437.       ColorMap=display.Screen->Screen->ViewPort.ColorMap;
  438.       ReleasePen(ColorMap,display.DynamicColor2);
  439.       ReleasePen(ColorMap,display.DynamicColor1);
  440.       display.dynamic=FALSE;
  441.     }
  442. }
  443.  
  444. /************************************************************************/
  445. /*                                    */
  446. /* Free the sprites                            */
  447. /*                                    */
  448. /************************************************************************/
  449.  
  450. static void FreeSprites(void)
  451.  
  452. {
  453.   if (Sprites!=NULL)
  454.     {
  455.       if (display.window!=NULL)
  456.     {
  457.       SetABPenDrMd(display.window->RPort,0,0,JAM1);
  458.       RectFill(display.window->RPort,display.OriginX,display.OriginY,
  459.            display.OriginX+WINDOW_WIDTH-1,display.OriginY+WINDOW_HEIGHT-1);
  460.     }
  461.       ReleaseDynamic();
  462.       GS_FreeSprites(Sprites,display.Screen->Screen);
  463.       Sprites=NULL;
  464.       FreeSysRequest(About);
  465.       About=NULL;
  466.     }
  467. }
  468.  
  469. /************************************************************************/
  470. /*                                    */
  471. /* Process a "key".                            */
  472. /*                                    */
  473. /************************************************************************/
  474.  
  475. static INLINE void KeyDown(int Key)
  476.  
  477. {
  478.   global.pressed|=1<<Key;
  479.   if (Key==KEY_PAUSE)
  480.     {
  481.       timer_set((unsigned long)0, TIMING_PAUSE);
  482.       global.pause = 1;
  483.     }
  484. }
  485.  
  486. /************************************************************************/
  487.  
  488. static INLINE void KeyUp(int Key)
  489.  
  490. {
  491.   global.pressed&=~(1<<Key);
  492. }
  493.  
  494. /************************************************************************/
  495. /*                                    */
  496. /*                                    */
  497. /************************************************************************/
  498.  
  499. static void InactiveWindow(void)
  500.  
  501. {
  502.   int Key;
  503.  
  504.   FreeJoystick();
  505.   if (MiscState.GameMode)
  506.     {
  507.       KeyDown(KEY_PAUSE);
  508.     }
  509.   for (Key=0; Key<KEYS; Key++)
  510.     {
  511.       KeyUp(Key);
  512.     }
  513. }
  514.  
  515. /************************************************************************/
  516. /*                                    */
  517. /* Free all GUI related resources (except for the menu)            */
  518. /*                                    */
  519. /************************************************************************/
  520.  
  521. static void CloseGUI(void)
  522.  
  523. {
  524.   if (!ErrorFlag)
  525.     {
  526.       CloseErrorWindow();
  527.     }
  528.   if (display.Screen!=NULL)
  529.     {
  530.       if (display.VisualInfo!=NULL)
  531.     {
  532.       if (display.window!=NULL)
  533.         {
  534.           InactiveWindow();
  535.           CloseConfigKeysWindow();
  536.           CloseChangeUserWindow();
  537.           CloseManual();
  538.           FreeSysRequest(CompileInfo);
  539.           CompileInfo=NULL;
  540.           global.pressed=0;
  541.           FreeSprites();
  542.           ClearMenuStrip(display.window);
  543.           ((struct Process *)WindowPort.mp_SigTask)->pr_WindowPtr=display.window->UserData;
  544.           CloseWindowSafely(display.window);
  545.           display.window=NULL;
  546.           FreeBitmaps();
  547.           if (IconifyImageClass!=NULL)
  548.         {
  549.           DisposeObject(IconifyGadget.GadgetRender);
  550.           IconifyGadget.GadgetRender=NULL;
  551.           FreeClass(IconifyImageClass);
  552.           IconifyImageClass=NULL;
  553.         }
  554.           if (MiscState.HappyBlanker)
  555.         {
  556.           MiscState.HappyBlanker=FALSE;
  557.           GS_NoHappyBlanker();
  558.         }
  559.         }
  560.       if (data.font!=NULL)
  561.         {
  562.           CloseFont(data.font);
  563.           data.font=NULL;
  564.         }
  565.       FreeVisualInfo(display.VisualInfo);
  566.       display.VisualInfo=NULL;
  567.     }
  568.       FreeScreenDrawInfo(display.Screen->Screen,display.DrawInfo);
  569.       if (FreeScreen(display.Screen,FALSE))
  570.     {
  571.       display.Screen=NULL;
  572.     }
  573.     }
  574.   ErrorFlag=FALSE;
  575. }
  576.  
  577. /************************************************************************/
  578. /*                                    */
  579. /* Change key description                        */
  580. /* In case of failure, the key is not changed.                */
  581. /* If Description==NULL, the default binding is used            */
  582. /*                                    */
  583. /************************************************************************/
  584.  
  585. int ChangeKey(int Key, char *Description)
  586.  
  587. {
  588.   if (Description==NULL)
  589.     {
  590.       if (Key==KEYS)
  591.     {
  592.       Description="help";
  593.     }
  594.       else if (Key==KEYS+1)
  595.     {
  596.       Description="lshift rshift help";
  597.     }
  598.       else
  599.     {
  600.       Description=GetString(MSG_KEY_UP+Key);
  601.     }
  602.       ParseIX(data.keysyms[Key].Description=Description,&data.keysyms[Key].InputXpression);
  603.     }
  604.   else
  605.     {
  606.       struct InputXpression InputXpression;
  607.       char *String;
  608.  
  609.       if (ParseIX(Description,&InputXpression)!=0 || InputXpression.ix_Class!=IECLASS_RAWKEY)
  610.     {
  611.       DisplayError(MSG_INVALIDKEY_ERROR,Description,GetString(MSG_DEMO_UP+Key));
  612.       return FALSE;
  613.     }
  614.       if ((String=GS_MemoryAlloc(strlen(Description)+1))==NULL)
  615.     {
  616.       DisplayError(0,ERROR_NO_FREE_STORE);
  617.       return FALSE;
  618.     }
  619.       if (data.keysyms[Key].Description!=GetString(MSG_KEY_UP+Key))
  620.     {
  621.       GS_MemoryFree(data.keysyms[Key].Description);
  622.     }
  623.       strcpy((data.keysyms[Key].Description=String),Description);
  624.       data.keysyms[Key].InputXpression=InputXpression;
  625.     }
  626.   return TRUE;
  627. }
  628.  
  629. /************************************************************************/
  630. /*                                    */
  631. /* Free key descriptions                        */
  632. /*                                    */
  633. /************************************************************************/
  634.  
  635. static INLINE void FreeKeys(void)
  636.  
  637. {
  638.   int Key;
  639.  
  640.   for (Key=0; Key<KEYS; Key++)
  641.     {
  642.       ChangeKey(Key,NULL);
  643.     }
  644. }
  645.  
  646. /************************************************************************/
  647. /*                                    */
  648. /*                                    */
  649. /************************************************************************/
  650.  
  651. static INLINE void FreeGardens(void)
  652.  
  653. {
  654.   struct Menu *Menu;
  655.  
  656.   Menu=FindMenu(MSG_GARDENS_MENU);
  657.   while (Menu->FirstItem!=NULL)
  658.     {
  659.       struct MenuItem *Item;
  660.  
  661.       Item=Menu->FirstItem;
  662.       Menu->FirstItem=Item->NextItem;
  663.       Item->NextItem=NULL;
  664.       FreeMenus((struct Menu *)Item);
  665.     }
  666. }
  667.  
  668. /************************************************************************/
  669. /*                                    */
  670. /*                                    */
  671. /************************************************************************/
  672.  
  673. static void CloseAll(int RC, LONG Error)
  674.  
  675. {
  676.   if (GadToolsBase!=NULL)
  677.     {
  678.       if (GameSupportBase!=NULL)
  679.     {
  680.       if (CxBase!=NULL)
  681.         {
  682.           CloseErrorWindow();
  683.           FreeErrors();
  684.           DeleteCxObj(Broker);
  685. #if !defined(__SASC)
  686.           if (DitherPattern!=NULL)
  687.         {
  688. #endif
  689.           CloseGUI();
  690.           if (board.list!=NULL)
  691.             {
  692.               FreeFile((LONG *)(((char *)board.list)-12)-1);
  693.             }
  694.           FreeKeys();
  695. #if !defined(__SASC)
  696.           FreeMem(DitherPattern,2*sizeof(UWORD));
  697.         }
  698. #endif
  699.           while (FontMessage.Message.mn_Node.ln_Type!=NT_UNKNOWN ||
  700.              ConfigMessage.Message.mn_Node.ln_Type!=NT_UNKNOWN ||
  701.              ScreenMessage.Message.mn_Node.ln_Type!=NT_UNKNOWN)
  702.         {
  703.           WaitPort(&MiscPort);
  704.           ProcessMisc();
  705.         }
  706.           while (ProcessMisc())
  707.         ;
  708.           GS_MemoryFree(WindowTitle);
  709.           GS_ReleaseScoreHandle(scoring.ScoreHandle);
  710.           if (display.Menustrip!=NULL)
  711.         {
  712.           FreeGardens();
  713.           FreeMenus(display.Menustrip);
  714.         }
  715.           while (GardenStrings!=NULL)
  716.         {
  717.           struct GardenString *Next;
  718.  
  719.           Next=GardenStrings->Next;
  720.           GS_MemoryFree(GardenStrings);
  721.           GardenStrings=Next;
  722.         }
  723.           if (Locale!=NULL)
  724.         {
  725.           CloseCatalog(Catalog);
  726.           CloseLocale(Locale);
  727.         }
  728.           FreeVec(TextAttr.ta_Name);
  729.           CloseLibrary(CxBase);
  730.           if (display.Screen!=NULL)
  731.         {
  732.           FreeScreen(display.Screen,TRUE);
  733.         }
  734.         }
  735.       if (GardenDir!=MKBADDR(NULL))
  736.         {
  737.           UnLock(GardenDir);
  738.         }
  739.       GS_MemoryFree(ScreenDescription);
  740.       GS_MemoryFree(NewBroker.nb_Name);
  741.       CloseLibrary(&GameSupportBase->Library);
  742.     }
  743.       CloseLibrary(GadToolsBase);
  744.       CloseLibrary(IconBase);
  745.     }
  746.   FreeSignal(MiscPort.mp_SigBit);
  747.   MyExit(RC,Error);
  748. }
  749.  
  750. /************************************************************************/
  751. /*                                    */
  752. /* Install a clipping rectangle into a Pixmap                */
  753. /*                                    */
  754. /************************************************************************/
  755.  
  756. struct Region *InstallBounds(Pixmap *Data, struct Rectangle Rectangle)
  757.  
  758. {
  759.   struct Region *Region;
  760.  
  761.   assert(Data->Layer!=NULL);
  762.   if ((Region=NewRegion())!=NULL)
  763.     {
  764.       if (OrRectRegion(Region,&Rectangle))
  765.     {
  766.       struct Region *OldRegion;
  767.  
  768.       OldRegion=InstallClipRegion(Data->Layer,Region);
  769.       assert(OldRegion==NULL);
  770.       return Region;
  771.     }
  772.       DisposeRegion(Region);
  773.     }
  774.   return NULL;
  775. }
  776.  
  777. /************************************************************************/
  778. /*                                    */
  779. /* Remove the current clipping rectangle from the Pixmap        */
  780. /*                                    */
  781. /************************************************************************/
  782.  
  783. void RemoveBounds(Pixmap *Data)
  784.  
  785. {
  786.   struct Region *Region;
  787.  
  788.   assert(Data->Layer!=NULL);
  789.   Region=InstallClipRegion(Data->Layer,NULL);
  790.   assert(Region!=NULL);
  791.   DisposeRegion(Region);
  792. }
  793.  
  794. /************************************************************************/
  795. /*                                    */
  796. /* Get a localized string                        */
  797. /*                                    */
  798. /************************************************************************/
  799.  
  800. const char *GetString(LONG StringID)
  801.  
  802. {
  803.   const char *String;
  804.  
  805.   String=LocaleBase!=NULL ? (char *)GetCatalogStr(Catalog,StringID,NULL) : NULL;
  806.   if (String==NULL)
  807.     {
  808.       const LONG *l;
  809.       const UWORD *w;
  810.  
  811.       l=(const LONG *)CatCompBlock;
  812.       while (*l != StringID)
  813.     {
  814.       w=(const UWORD *)((ULONG)l + 4);
  815.       l=(const LONG *)((ULONG)l + (ULONG)*w +6);
  816.     }
  817.       String=(char *)((ULONG)l + 6);
  818.     }
  819.   return String;
  820. }
  821.  
  822. /************************************************************************/
  823. /*                                    */
  824. /* Obtain dynamic colors, if required                    */
  825. /*                                    */
  826. /************************************************************************/
  827.  
  828. static void ObtainDynamic(void)
  829.  
  830. {
  831.   display.dynamic=FALSE;
  832.   if (GfxBase->LibNode.lib_Version>=39)
  833.     {
  834.       if (!data.mono)
  835.     {
  836.       struct ColorMap *ColorMap;
  837.  
  838.       if ((ColorMap=display.Screen->Screen->ViewPort.ColorMap)!=NULL)
  839.         {
  840.           if ((display.DynamicColor1=ObtainPen(ColorMap,-1,0,0,0,PENF_EXCLUSIVE | PENF_NO_SETCOLOR))!=~0)
  841.         {
  842.           if ((display.DynamicColor2=ObtainPen(ColorMap,-1,0,0,0,PENF_EXCLUSIVE | PENF_NO_SETCOLOR))!=~0)
  843.             {
  844.               display.dynamic=TRUE;
  845.             }
  846.           else
  847.             {
  848.               ReleasePen(ColorMap,display.DynamicColor1);
  849.             }
  850.         }
  851.         }
  852.     }
  853.     }
  854. }
  855.  
  856. /************************************************************************/
  857. /*                                    */
  858. /*                                    */
  859. /************************************************************************/
  860.  
  861. void Sleep(void)
  862.  
  863. {
  864.   MiscState.Sleep=TRUE;
  865.   GS_WindowSleep(display.window);
  866.   GS_WindowSleep(ConfigKeysWindow);
  867.   GS_WindowSleep(ChangeUserWindow);
  868.   GS_WindowSleep(ErrorWindow);
  869. }
  870.  
  871. /************************************************************************/
  872.  
  873. void Wakeup(void)
  874.  
  875. {
  876.   MiscState.Sleep=FALSE;
  877.   GS_WindowWakeup(ChangeUserWindow);
  878.   GS_WindowWakeup(ConfigKeysWindow);
  879.   GS_WindowWakeup(display.window);
  880.   GS_WindowWakeup(ErrorWindow);
  881. }
  882.  
  883. /************************************************************************/
  884. /*                                    */
  885. /* Load the sprites                            */
  886. /*                                    */
  887. /************************************************************************/
  888.  
  889. static int LoadSprites(void)
  890.  
  891. {
  892.   struct MenuItem *Item;
  893.   const char *Name;
  894.   ULONG Gender;
  895.  
  896.   Sleep();
  897.   Item=(struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_MSIT_MENU);
  898.   Gender=!!(Item->Flags & CHECKED);
  899.   Name=Gender ? "msit" : "mris";
  900.   if ((Sprites=GS_LoadSprites(Name,display.Screen->Screen))==NULL)
  901.     {
  902.       char String[ERRORSTRING_LENGTH];
  903.  
  904.       DisplayError(MSG_SPRITES_ERROR,Name,ErrorString(String,IoErr()));
  905.       Gender=!Gender;
  906.       Name=Gender ? "msit" : "mris";
  907.       if ((Sprites=GS_LoadSprites(Name,display.Screen->Screen))==NULL)
  908.     {
  909.       DisplayError(MSG_SPRITES_ERROR,Name,ErrorString(String,IoErr()));
  910.     }
  911.     }
  912.   if (Sprites!=NULL)
  913.     {
  914.       WORD x;
  915.       struct RastPort RastPort;
  916.  
  917.       data.gender=Gender;
  918.       ClearMenuStrip(display.window);
  919.       if (Gender)
  920.     {
  921.       Item->Flags|=CHECKED;
  922.       memcpy(ball_hold,she_hold,sizeof(ball_hold));
  923.       lettering[0] = letter_msit;
  924.     }
  925.       else
  926.     {
  927.       Item->Flags&=~CHECKED;
  928.       memcpy(ball_hold,he_hold,sizeof(ball_hold));
  929.       lettering[0] = letter_mris;
  930.     }
  931.       ResetMenuStrip(display.window,display.Menustrip);
  932.  
  933.       sprites=(SPRITE *)Sprites->Sprites;
  934.       InitRastPort(&RastPort);
  935.       RastPort.BitMap=sprites[SPRITE_SPECIAL].image;
  936.       for (x=0; x<=7; x++)
  937.     {
  938.       backgrounds[x>>1][x&1]=ReadPixel(&RastPort,x,0);
  939.     }
  940.       display.black=ReadPixel(&RastPort,8,0);
  941.       display.white=ReadPixel(&RastPort,9,0);
  942.       display.border=ReadPixel(&RastPort,10,0);
  943.  
  944.       data.mono=(Sprites->Colors.ColorCount==2);
  945.       if (((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_DYNAMIC_MENU))->Flags&CHECKED)
  946.     {
  947.       ObtainDynamic();
  948.     }
  949.  
  950.       /* create display.xorBitmap */
  951.       {
  952.     ULONG xor;
  953.     int Plane;
  954.  
  955.     xor=display.black^display.white;
  956.     assert((xor&~0xff)==0);
  957.     for (Plane=0; Plane<ARRAYSIZE(display.xorBitmap.Planes); Plane++)
  958.       {
  959.         display.xorBitmap.Planes[Plane]=(xor&(1<<Plane)) ? (PLANEPTR)~0 : (PLANEPTR)0;
  960.       }
  961.     display.xorBitmap.Depth=ARRAYSIZE(display.xorBitmap.Planes);
  962.     display.xorBitmap.BytesPerRow=((WINDOW_WIDTH+15)/16)*2;
  963.     display.xorBitmap.Rows=WINDOW_HEIGHT;
  964.       }
  965.  
  966.       /*{{{  set foreground & background types*/
  967.       {
  968.     ULONG Set;
  969.     ULONG Clear;
  970.     ULONG i;
  971.     
  972.     Set = 0;
  973.     Clear = (1<<display.DrawInfo->dri_Depth)-1;
  974.     /*{{{  set on and off*/
  975.     for(i=0; i<Sprites->Colors.ColorCount; i++)
  976.       {
  977.         Set|=Sprites->Colors.Colors[i].Pen;
  978.         Clear&=Sprites->Colors.Colors[i].Pen;
  979.       }
  980.     /*}}}*/
  981.     display.background = display.white == Clear ? COLOUR_ZERO :
  982.       display.white == Set ? COLOUR_ONE : COLOUR_WEIRD;
  983.     display.foreground = display.black == Clear ? COLOUR_ZERO :
  984.       display.black == Set ? COLOUR_ONE : COLOUR_WEIRD;
  985.       }
  986.  
  987.       /*{{{  create fills*/
  988.       if (data.mono)
  989.     {
  990.       int i;
  991.  
  992.       SetDrMd(&RastPort,JAM1);
  993.       SetAfPt(&RastPort,DitherPattern,1);
  994.       for (i=0; i<FILLS; i++)
  995.         {
  996.           SPRITE *sptr;
  997.  
  998.           sptr=&sprites[SPRITE_FILLS+i];
  999.           RastPort.BitMap=sptr->image;
  1000.           RectFill(&RastPort,0,0,sptr->size.x-1,sptr->size.y-1);
  1001.         }
  1002.     }
  1003.  
  1004.       /*{{{  digits special*/
  1005.       {
  1006.     SPRITE    *dptr;
  1007.  
  1008.     dptr = &sprites[SPRITE_DIGITS];
  1009.     XFillRectangle(display.display, display.back, GCN(GC_CLEAR),
  1010.                0, 0, dptr->size.x, dptr->size.y);
  1011.     XCopyArea(display.display, dptr->mask, display.back, GCN(GC_MASK),
  1012.           0, 0, dptr->size.x, dptr->size.y, 0, 0);
  1013.     XCopyArea(display.display, display.back, dptr->image, GCN(GC_OR),
  1014.           0, 0, dptr->size.x, dptr->size.y, 0, 0);
  1015.       }
  1016.     }
  1017.   Wakeup();
  1018.   BeginRefresh(display.window);
  1019.   EndRefresh(display.window,TRUE);
  1020.   return Sprites!=NULL;
  1021. }
  1022.  
  1023. /************************************************************************/
  1024. /*                                    */
  1025. /* Allocate a fullsize offscreen bitmap                    */
  1026. /*                                    */
  1027. /************************************************************************/
  1028.  
  1029. static int CreateOffscreen(Pixmap *Data)
  1030.  
  1031. {
  1032.   if ((Data->LayerInfo=NewLayerInfo())!=NULL)
  1033.     {
  1034.       Data->BitMap=AllocBitMap(WINDOW_WIDTH,WINDOW_HEIGHT,display.DrawInfo->dri_Depth,
  1035.                    BMF_CLEAR | BMF_INTERLEAVED,display.Screen->Screen->RastPort.BitMap);
  1036.       if (Data->BitMap!=NULL)
  1037.     {
  1038.       Data->Layer=CreateBehindLayer(Data->LayerInfo,Data->BitMap,0,0,WINDOW_WIDTH-1,WINDOW_HEIGHT-1,LAYERSIMPLE,NULL);
  1039.       if (Data->Layer!=NULL)
  1040.         {
  1041.           SetFont(Data->Layer->rp,data.font);
  1042.           return TRUE;
  1043.         }
  1044.     }
  1045.     }
  1046.   return FALSE;
  1047. }
  1048.  
  1049. /************************************************************************/
  1050. /*                                    */
  1051. /* Allocate our various offscreen bitmaps                */
  1052. /*                                    */
  1053. /************************************************************************/
  1054.  
  1055. static INLINE int AllocateBitmaps(void)
  1056.  
  1057. {
  1058.   if (CreateOffscreen(&display.copy))
  1059.     {
  1060.       if (CreateOffscreen(&display.back))
  1061.     {
  1062.       int  i;
  1063.  
  1064.       for (i=0; i<BOARD_SCORES; i++)
  1065.         {
  1066.           update.score.list[i].image.BitMap=AllocBitMap(DIGIT_WIDTH*4,DIGIT_HEIGHT,display.DrawInfo->dri_Depth,
  1067.                                 BMF_INTERLEAVED,display.Screen->Screen->RastPort.BitMap);
  1068.           if (update.score.list[i].image.BitMap==NULL)
  1069.         {
  1070.           break;
  1071.         }
  1072.           update.score.list[i].mask.BitMap=AllocBitMap(DIGIT_WIDTH*4,DIGIT_HEIGHT,display.DrawInfo->dri_Depth,
  1073.                                BMF_INTERLEAVED,display.Screen->Screen->RastPort.BitMap);
  1074.           if (update.score.list[i].mask.BitMap==NULL)
  1075.         {
  1076.           break;
  1077.         }
  1078.         }
  1079.       if (i==BOARD_SCORES)
  1080.         {
  1081.           return TRUE;
  1082.         }
  1083.     }
  1084.     }
  1085.   FreeBitmaps();
  1086.   return FALSE;
  1087. }
  1088.  
  1089. /************************************************************************/
  1090. /*                                    */
  1091. /* Process an JoystickEvent                        */
  1092. /*                                    */
  1093. /************************************************************************/
  1094.  
  1095. static INLINE void HandleJoystick(void)
  1096.  
  1097. {
  1098.   switch (GameSupportBase->Joystick.Event.ie_Code)
  1099.     {
  1100.     case IECODE_LBUTTON:
  1101.       KeyDown(KEY_THROW);
  1102.       break;
  1103.  
  1104.     case IECODE_RBUTTON:
  1105.       KeyDown(KEY_PAUSE);
  1106.       break;
  1107.  
  1108.     case IECODE_LBUTTON | IECODE_UP_PREFIX:
  1109.       KeyUp(KEY_THROW);
  1110.       break;
  1111.  
  1112.     case IECODE_RBUTTON | IECODE_UP_PREFIX:
  1113.       KeyUp(KEY_PAUSE);
  1114.       break;
  1115.  
  1116.     case IECODE_NOBUTTON:
  1117.       switch (GameSupportBase->Joystick.Event.ie_X)
  1118.     {
  1119.     case 1:
  1120.       KeyUp(KEY_LEFT);
  1121.       KeyDown(KEY_RIGHT);
  1122.       break;
  1123.  
  1124.     case -1:
  1125.       KeyUp(KEY_RIGHT);
  1126.       KeyDown(KEY_LEFT);
  1127.       break;
  1128.  
  1129.     case 0:
  1130.       KeyUp(KEY_RIGHT);
  1131.       KeyUp(KEY_LEFT);
  1132.       break;
  1133.     }
  1134.  
  1135.       switch (GameSupportBase->Joystick.Event.ie_Y)
  1136.     {
  1137.     case 1:
  1138.       KeyUp(KEY_UP);
  1139.       KeyDown(KEY_DOWN);
  1140.       break;
  1141.  
  1142.     case -1:
  1143.       KeyUp(KEY_DOWN);
  1144.       KeyDown(KEY_UP);
  1145.       break;
  1146.  
  1147.     case 0:
  1148.       KeyUp(KEY_UP);
  1149.       KeyUp(KEY_DOWN);
  1150.       break;
  1151.     }
  1152.       break;
  1153.     }
  1154.   GS_SendJoystick();
  1155. }
  1156.  
  1157. /************************************************************************/
  1158. /*                                    */
  1159. /* Create a message window                        */
  1160. /*                                    */
  1161. /************************************************************************/
  1162.  
  1163. static struct Window *CreateMessage(const char *Title, const char *Template, ...)
  1164.  
  1165. {
  1166.   struct EasyStruct EasyStruct;
  1167.   struct Window *Window;
  1168.  
  1169.   EasyStruct.es_StructSize=5*4;
  1170.   EasyStruct.es_Flags=0;
  1171.   EasyStruct.es_Title=(char *)Title;
  1172.   EasyStruct.es_TextFormat=(char *)Template;
  1173.   EasyStruct.es_GadgetFormat=GetString(MSG_MESSAGE_WINDOW_CLOSE);
  1174.   Window=BuildEasyRequestArgs(display.window,&EasyStruct,0,&Template+1);
  1175.   if (Window==(struct Window *)1)
  1176.     {
  1177.       Window=NULL;
  1178.     }
  1179.   return Window;
  1180. }
  1181.  
  1182. /************************************************************************/
  1183. /*                                    */
  1184. /* Process an IDCMP_RAWKEY event                    */
  1185. /*                                    */
  1186. /************************************************************************/
  1187.  
  1188. static INLINE void HandleKey(const struct IntuiMessage *Message)
  1189.  
  1190. {
  1191.   if (!(Message->Qualifier & IEQUALIFIER_REPEAT))
  1192.     {
  1193.       struct InputEvent InputEvent;
  1194.       int Key;
  1195.  
  1196.       InputEvent.ie_NextEvent=NULL;
  1197.       InputEvent.ie_Class=IECLASS_RAWKEY;
  1198.       InputEvent.ie_SubClass=0;
  1199.       InputEvent.ie_Code=Message->Code&~IECODE_UP_PREFIX;
  1200.       InputEvent.ie_Qualifier=Message->Qualifier;
  1201.       InputEvent.ie_position.ie_addr=*(APTR *)Message->IAddress;
  1202.       InputEvent.ie_TimeStamp.tv_secs=Message->Seconds;
  1203.       InputEvent.ie_TimeStamp.tv_micro=Message->Micros;
  1204.       for (Key=0; Key<ARRAYSIZE(data.keysyms); Key++)
  1205.     {
  1206.       if (MatchIX(&InputEvent,&data.keysyms[Key].InputXpression))
  1207.         {
  1208.           if (Key<KEYS)
  1209.         {
  1210.           ((Message->Code&IECODE_UP_PREFIX) ? KeyUp : KeyDown)(Key);
  1211.         }
  1212.           else if (Key==KEYS)
  1213.         {
  1214.           if (!(Message->Code&IECODE_UP_PREFIX))
  1215.             {
  1216.               OpenManual();
  1217.             }
  1218.         }
  1219.           else
  1220.         {
  1221.           assert(Key==KEYS+1);
  1222.           if (!(Message->Code&IECODE_UP_PREFIX))
  1223.             {
  1224.               if (CompileInfo==NULL)
  1225.             {
  1226.               CompileInfo=
  1227.                 CreateMessage(PROGRAM_NAME " " PROGRAM_VERSION " (" PROGRAM_DATE ")",
  1228.                       "Compiler: " COMPILER "\n"
  1229.                       "Date: %s, %s\n"
  1230.                       "CPU: " CPU "\n"
  1231.                       "AmigaOS: V%ld (Release " ROM_RELEASE ")",
  1232.                       CompileDate, CompileTime, ROM_VERSION);
  1233.             }
  1234.             }
  1235.         }
  1236.           break;
  1237.         }
  1238.     }
  1239.     }
  1240. }
  1241.  
  1242. /************************************************************************/
  1243. /*                                    */
  1244. /* Open the game font                            */
  1245. /*                                    */
  1246. /************************************************************************/
  1247.  
  1248. static INLINE int ObtainFont(void)
  1249.  
  1250. {
  1251.   if ((DiskfontBase=OpenLibrary((char *)DiskfontName,0))==NULL)
  1252.     {
  1253.       DisplayError(MSG_NO_LIBRARY,DiskfontName);
  1254.     }
  1255.   if (TextAttr.ta_Name!=NULL)
  1256.     {
  1257.       if ((data.font=(DiskfontBase!=NULL ? OpenDiskFont : OpenFont)(&TextAttr))==NULL)
  1258.     {
  1259.       DisplayError(MSG_FONT_ERROR,TextAttr.ta_Name,TextAttr.ta_YSize);
  1260.     }
  1261.     }
  1262.   if (data.font==NULL)
  1263.     {
  1264.       static struct TextAttr TimesAttr={"Times.font", 18, 0, 0};
  1265.  
  1266.       data.font=(DiskfontBase!=NULL ? OpenDiskFont : OpenFont)(&TimesAttr);
  1267.       if (data.font==NULL)
  1268.     {
  1269.       DisplayError(MSG_FONT_ERROR,TimesAttr.ta_Name,TimesAttr.ta_YSize);
  1270.       data.font=OpenFont(display.Screen->Screen->Font);
  1271.       if (data.font==NULL)
  1272.         {
  1273.           static struct TextAttr TopazAttr={"topaz.font", 9, 0, 0};
  1274.  
  1275.           data.font=OpenFont(&TopazAttr);
  1276.         }
  1277.     }
  1278.     }
  1279.   CloseLibrary(DiskfontBase);
  1280.   return data.font!=NULL;
  1281. }
  1282.  
  1283. /************************************************************************/
  1284. /*                                    */
  1285. /* Make an iconify gadget for our window                */
  1286. /*                                    */
  1287. /************************************************************************/
  1288.  
  1289. static INLINE void CreateIconifyGadget(void)
  1290.  
  1291. {
  1292.   if (CreateIconifyImageClass()!=NULL)
  1293.     {
  1294.       if ((IconifyGadget.GadgetRender=NewObjectA(IconifyImageClass,NULL,NULL))!=NULL)
  1295.     {
  1296.       Object *DepthImage;
  1297.  
  1298.       IconifyGadget.SelectRender=IconifyGadget.GadgetRender;
  1299.       DepthImage=NewObject(NULL, SYSICLASS,
  1300.                    SYSIA_DrawInfo, display.DrawInfo,
  1301.                    SYSIA_Which, DEPTHIMAGE,
  1302.                    SYSIA_Size, ((display.Screen->Screen->Flags & SCREENHIRES) ?
  1303.                         ((display.Screen->Screen->ViewPort.Modes & LACE) ?
  1304.                          SYSISIZE_HIRES : SYSISIZE_MEDRES) :
  1305.                         SYSISIZE_LOWRES),
  1306.                    TAG_DONE);
  1307.       if (DepthImage!=NULL)
  1308.         {
  1309.           {
  1310.         ULONG Width;
  1311.  
  1312.         GetAttr(IA_Width,DepthImage,&Width);
  1313.         IconifyGadget.Width=(WORD)Width;
  1314.           }
  1315.           DisposeObject(DepthImage);
  1316.           IconifyGadget.LeftEdge=display.window->BorderRight-2*IconifyGadget.Width;
  1317.           IconifyGadget.Height=display.window->BorderTop;
  1318.           ((struct Image *)IconifyGadget.GadgetRender)->Width=IconifyGadget.Width;
  1319.           ((struct Image *)IconifyGadget.GadgetRender)->Height=IconifyGadget.Height;
  1320.           AddGadget(display.window,&IconifyGadget,0);
  1321.           RefreshGadgets(display.window->FirstGadget,display.window,NULL);
  1322.         }
  1323.     }
  1324.     }
  1325. }
  1326.  
  1327. /************************************************************************/
  1328. /*                                    */
  1329. /* Allocate all GUI related resources (except for the menu)        */
  1330. /*                                    */
  1331. /************************************************************************/
  1332.  
  1333. static void OpenGUI(void)
  1334.  
  1335. {
  1336.   if (display.Screen!=NULL || (display.Screen=GetScreen(ScreenDescription,NewBroker.nb_Name))!=NULL)
  1337.     {
  1338.       display.DrawInfo=GetScreenDrawInfo(display.Screen->Screen);
  1339.       if ((display.VisualInfo=GetVisualInfo(display.Screen->Screen,NULL))!=NULL)
  1340.     {
  1341.       static struct TagItem LayoutTags[]=
  1342.         {
  1343.           {GTMN_NewLookMenus, TRUE},
  1344.           {TAG_DONE}
  1345.         };
  1346.  
  1347.       LayoutMenusA(display.Menustrip,display.VisualInfo,LayoutTags);
  1348.       if (ObtainFont())
  1349.         {
  1350.           WORD X, Y, Width, Height;
  1351.           ULONG IntuiLock;
  1352.  
  1353.           IntuiLock=LockIBase(0);
  1354.           X=display.Screen->Screen->MouseX;
  1355.           Y=display.Screen->Screen->MouseY;
  1356.           UnlockIBase(IntuiLock);
  1357.           display.OriginX=display.Screen->Screen->WBorLeft;
  1358.           display.OriginY=display.Screen->Screen->WBorTop+display.Screen->Screen->Font->ta_YSize+1;
  1359.           Width=WINDOW_WIDTH+display.OriginX+display.Screen->Screen->WBorRight;
  1360.           Height=WINDOW_HEIGHT+display.OriginY+display.Screen->Screen->WBorBottom;
  1361.           if (Width<=display.Screen->Screen->Width && Height<=display.Screen->Screen->Height)
  1362.         {
  1363.           static struct TagItem WindowTags[]=
  1364.             {
  1365.               {WA_Flags,  WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_SIMPLE_REFRESH | WFLG_ACTIVATE | WFLG_NEWLOOKMENUS},
  1366.               {WA_RptQueue, 0},
  1367.               {WA_PointerDelay, TRUE},
  1368.               {TAG_DONE}
  1369.             };
  1370.  
  1371.           X-=Width/2;
  1372.           Y-=Height/2;
  1373.           display.window=OpenWindowTags(NULL,
  1374.                         WA_Left, X,
  1375.                         WA_Top, Y,
  1376.                         WA_Width, Width,
  1377.                         WA_Height, Height,
  1378.                         WA_ScreenTitle, GetString(MSG_SCREEN_TITLE),
  1379.                         WA_PubScreen, display.Screen->Screen,
  1380.                         WA_Title, WindowTitle,
  1381.                         TAG_MORE, WindowTags);
  1382.           if (display.window!=NULL)
  1383.             {
  1384.               display.window->UserData=((struct Process *)WindowPort.mp_SigTask)->pr_WindowPtr;
  1385.               ((struct Process *)WindowPort.mp_SigTask)->pr_WindowPtr=display.window;
  1386.               CreateIconifyGadget();
  1387.               if (AllocateBitmaps())
  1388.             {
  1389.               if (LoadSprites())
  1390.                 {
  1391.                   SetMenuStrip(display.window,display.Menustrip);
  1392.                   display.window->UserPort=&WindowPort;
  1393.                   ModifyIDCMP(display.window,
  1394.                       IDCMP_MENUPICK |
  1395.                       IDCMP_GADGETUP |
  1396.                       IDCMP_CLOSEWINDOW |
  1397.                       IDCMP_REFRESHWINDOW |
  1398.                       IDCMP_RAWKEY |
  1399.                       IDCMP_ACTIVEWINDOW |
  1400.                       IDCMP_INACTIVEWINDOW);
  1401.                   if (display.window->Flags & WFLG_WINDOWACTIVE)
  1402.                 {
  1403.                   AllocateJoystickCounter=JOYSTICK_TRIES;
  1404.                 }
  1405.                   if (scoring.UserName[0]=='\0')
  1406.                 {
  1407.                   OpenChangeUserWindow();
  1408.                 }
  1409.                   return;
  1410.                 }
  1411.             }
  1412.               else
  1413.             {
  1414.               DisplayError(0,ERROR_NO_FREE_STORE);
  1415.             }
  1416.             }
  1417.           else
  1418.             {
  1419.               DisplayError(MSG_WINDOW_ERROR);
  1420.             }
  1421.         }
  1422.           else
  1423.         {
  1424.           DisplayError(MSG_SCREENSIZE_ERROR,ScreenDescription,Width,Height);
  1425.         }
  1426.         }
  1427.     }
  1428.       else
  1429.     {
  1430.       DisplayError(0,ERROR_NO_FREE_STORE);
  1431.     }
  1432.     }
  1433.   else
  1434.     {
  1435.       LONG Error;
  1436.  
  1437.       Error=IoErr();
  1438.       if (Error==OSERR_PUBNOTUNIQUE)
  1439.     {
  1440.       char *String;
  1441.  
  1442.       String=GS_FormatString(GetString(MSG_OSERR_PUBNOTUNIQUE),&NewBroker.nb_Name,NULL,NULL);
  1443.       DisplayError(MSG_SCREEN_ERROR,ScreenDescription,String);
  1444.       GS_MemoryFree(String);
  1445.     }
  1446.       else
  1447.     {
  1448.       char String[ERRORSTRING_LENGTH];
  1449.  
  1450.       DisplayError(MSG_SCREEN_ERROR,ScreenDescription,ErrorString(String,Error));
  1451.     }
  1452.     }
  1453.   CloseGUI();
  1454. }
  1455.  
  1456. /************************************************************************/
  1457. /*                                    */
  1458. /* Handle config/control/joystick menu change                */
  1459. /*                                    */
  1460. /************************************************************************/
  1461.  
  1462. static INLINE void ChangeJoystick(const struct MenuItem *Item)
  1463.  
  1464. {
  1465.   if (Item->Flags & CHECKED)
  1466.     {
  1467.       if (!MiscState.Joystick)
  1468.     {
  1469.       AllocateJoystickCounter=JOYSTICK_TRIES;
  1470.     }
  1471.     }
  1472.   else
  1473.     {
  1474.       FreeJoystick();
  1475.     }
  1476. }
  1477.  
  1478. /************************************************************************/
  1479. /*                                    */
  1480. /* Handle config/display/msit menu change                */
  1481. /*                                    */
  1482. /************************************************************************/
  1483.  
  1484. static INLINE int ChangeGender(const struct MenuItem *Item)
  1485.  
  1486. {
  1487.   if (data.gender!=!!(Item->Flags & CHECKED))
  1488.     {
  1489.       FreeSprites();
  1490.       if (LoadSprites())
  1491.     {
  1492.       return TRUE;
  1493.     }
  1494.       CloseGUI();
  1495.     }
  1496.   return FALSE;
  1497. }
  1498.  
  1499. /************************************************************************/
  1500. /*                                    */
  1501. /* Handle config/display/dynamic menu change                */
  1502. /*                                    */
  1503. /************************************************************************/
  1504.  
  1505. static INLINE int ChangeDynamic(const struct MenuItem *Item)
  1506.  
  1507. {
  1508.   if (Item->Flags & CHECKED)
  1509.     {
  1510.       if (!display.dynamic)
  1511.     {
  1512.       ObtainDynamic();
  1513.       return (int)display.dynamic;
  1514.     }
  1515.     }
  1516.   else if (display.dynamic)
  1517.     {
  1518.       ReleaseDynamic();
  1519.       return TRUE;
  1520.     }
  1521.   return FALSE;
  1522. }
  1523.  
  1524. /************************************************************************/
  1525. /*                                    */
  1526. /* Set the window title                            */
  1527. /*                                    */
  1528. /************************************************************************/
  1529.  
  1530. void UpdateWindowTitle(void)
  1531.  
  1532. {
  1533.   struct
  1534.     {
  1535.       const char *User;
  1536.       const char *Garden;
  1537.     } Params;
  1538.  
  1539.   GS_MemoryFree(WindowTitle);
  1540.   if (scoring.UserName[0]!='\0')
  1541.     {
  1542.       Params.User=scoring.UserName;
  1543.     }
  1544.   else
  1545.     {
  1546.       Params.User=GetString(MSG_USER_UNKNOWN);
  1547.     }
  1548.   if (board.Name==NULL)
  1549.     {
  1550.       WindowTitle=GS_FormatString("%s",&Params.User,NULL,Locale);
  1551.     }
  1552.   else
  1553.     {
  1554.       Params.Garden=board.Name;
  1555.       WindowTitle=GS_FormatString("%s: %s",&Params,NULL,Locale);
  1556.     }
  1557.   if (display.window!=NULL)
  1558.     {
  1559.       SetWindowTitles(display.window,WindowTitle,(UBYTE *)~0);
  1560.     }
  1561.   scoring.mine.score=0;
  1562. }
  1563.  
  1564. /************************************************************************/
  1565. /*                                    */
  1566. /*                                    */
  1567. /************************************************************************/
  1568.  
  1569. static void HandleMessageWindow(struct Window **WindowPtr)
  1570.  
  1571. {
  1572.   struct Window *Window;
  1573.  
  1574.   Window=*WindowPtr;
  1575.   if (Window!=NULL)
  1576.     {
  1577.       if (SysReqHandler(Window,NULL,FALSE)!=-2)
  1578.     {
  1579.       FreeSysRequest(Window);
  1580.       *WindowPtr=NULL;
  1581.     }
  1582.     }
  1583. }
  1584.  
  1585. /************************************************************************/
  1586.  
  1587. static void EnableMenu(UWORD ID, int Item)
  1588.  
  1589. {
  1590.   struct Menu *Menu;
  1591.  
  1592.   Menu=(struct Menu *)FindMenu(ID);
  1593.   if (display.window!=NULL)
  1594.     {
  1595.       OnMenu(display.window,((ULONG)(Item ? GTMENUITEM_USERDATA(Menu) : GTMENU_USERDATA(Menu)))>>16);
  1596.     }
  1597.   else
  1598.     {
  1599.       Menu->Flags|=Item ? ITEMENABLED : MENUENABLED;
  1600.     }
  1601. }
  1602.  
  1603. /************************************************************************/
  1604. /*                                    */
  1605. /* Load selected boards.                        */
  1606. /* Returns TRUE if boards have changed.                    */
  1607. /*                                    */
  1608. /************************************************************************/
  1609.  
  1610. static int LoadBoards(void)
  1611.  
  1612. {
  1613.   static struct MenuItem *BoardItem;
  1614.  
  1615.   struct MenuItem *Item;
  1616.   struct StringNode *Name;
  1617.  
  1618.   for (Item=((struct Menu *)FindMenu(MSG_GARDENS_MENU))->FirstItem, Name=GardenStrings;
  1619.        Item!=NULL && !(Item->Flags&CHECKED);
  1620.        Item=Item->NextItem, Name=Name->Next)
  1621.     {
  1622.       assert(Name!=NULL);
  1623.     }
  1624.   if (Item!=NULL && BoardItem!=Item)
  1625.     {
  1626.       LONG *File;
  1627.       BPTR OldCurrentDir;
  1628.  
  1629.       OldCurrentDir=CurrentDir(GardenDir);
  1630.       if ((File=ReadFile(((char *)(Name+1))+1))!=NULL)
  1631.     {
  1632.       LONG Size;
  1633.  
  1634.       Size=(*File)-12;
  1635.       if (Size>0 && ((Size%sizeof(BOARD))==0) && strncmp((char *)(File+1),"mris Garden!",12)==0)
  1636.         {
  1637.           LONG i;
  1638.  
  1639.           for (i=0; i<Size/sizeof(BOARD); i++)
  1640.         {
  1641.           if (check_board(((BOARD *)(((char *)(File+1))+12))+i))
  1642.             {
  1643.               DisplayError(MSG_LOADGARDEN_ERROR,((char *)(Name+1))+1,GetString(MSG_INVALIDGARDEN_ERROR));
  1644.               Size=0;
  1645.             }
  1646.         }
  1647.           if (Size>0)
  1648.         {
  1649.           if (board.list!=NULL)
  1650.             {
  1651.               FreeFile((LONG *)(((char *)board.list)-12)-1);
  1652.             }
  1653.           board.Name=((char *)(Name+1))+1;
  1654.           board.boards=Size/sizeof(BOARD);
  1655.           board.list=(BOARD *)(((char *)(File+1))+12);
  1656.           BoardItem=Item;
  1657.           CurrentDir(OldCurrentDir);
  1658.           GS_ReleaseScoreHandle(scoring.ScoreHandle);
  1659.           scoring.ScoreHandle=NULL;
  1660.           UpdateWindowTitle();
  1661.           EnableMenu(MSG_DEMO_BOARD_MENU,TRUE);
  1662.           EnableMenu(MSG_DEMO_SCORES_MENU,TRUE);
  1663.           return TRUE;
  1664.         }
  1665.         }
  1666.       else
  1667.         {
  1668.           DisplayError(MSG_LOADGARDEN_ERROR,((char *)(Name+1))+1,GetString(MSG_NOGARDEN_ERROR));
  1669.         }
  1670.       FreeFile(File);
  1671.     }
  1672.       else
  1673.     {
  1674.       char String[ERRORSTRING_LENGTH];
  1675.  
  1676.       DisplayError(MSG_LOADGARDEN_ERROR,((char *)(Name+1))+1,ErrorString(String,IoErr()));
  1677.     }
  1678.       CurrentDir(OldCurrentDir);
  1679.       if (display.window!=NULL)
  1680.     {
  1681.       ClearMenuStrip(display.window);
  1682.       BoardItem->Flags|=CHECKED;
  1683.       Item->Flags&=~CHECKED;
  1684.       ResetMenuStrip(display.window,display.Menustrip);
  1685.     }
  1686.     }
  1687.   return FALSE;
  1688. }
  1689.  
  1690. /************************************************************************/
  1691.  
  1692. static struct DiskObject *GetPutDiskObject(struct DiskObject *DiskObject, char *Name)
  1693.  
  1694. {
  1695.   if (DiskObject==NULL)
  1696.     {
  1697.       if ((DiskObject=GetDiskObject(Name))==NULL)
  1698.     {
  1699.       LONG Error;
  1700.  
  1701.       Error=IoErr();
  1702.       if (Error==ERROR_OBJECT_NOT_FOUND)
  1703.         {
  1704.           DiskObject=&mrisIcon;
  1705.         }
  1706.       else
  1707.         {
  1708.           char String[ERRORSTRING_LENGTH];
  1709.  
  1710.           DisplayError(MSG_GETICON_ERROR,Name,ErrorString(String,Error));
  1711.         }
  1712.     }
  1713.     }
  1714.   else
  1715.     {
  1716.       if (!PutDiskObject(Name,DiskObject))
  1717.     {
  1718.       char String[ERRORSTRING_LENGTH];
  1719.  
  1720.       DisplayError(MSG_PUTICON_ERROR,Name,ErrorString(String,IoErr()));
  1721.       DiskObject=NULL;
  1722.     }
  1723.     }
  1724.   return DiskObject;
  1725. }
  1726.  
  1727. /************************************************************************/
  1728. /*                                    */
  1729. /* Get or Put the default icon                        */
  1730. /* If DiskObject==NULL, then get the default icon.            */
  1731. /* If DiskObject!=NULL, then write it as default icon.            */
  1732. /*                                    */
  1733. /************************************************************************/
  1734.  
  1735. static struct DiskObject *DoDefaultIcon(struct DiskObject *DiskObject)
  1736.  
  1737. {
  1738.   BPTR OldCurrentDir;
  1739.  
  1740.   if (WorkbenchMessage!=NULL)
  1741.     {
  1742.       assert(WorkbenchMessage->sm_NumArgs>0 && WorkbenchMessage->sm_ArgList[0].wa_Name!=NULL);
  1743.       OldCurrentDir=CurrentDir(WorkbenchMessage->sm_ArgList[0].wa_Lock);
  1744.       DiskObject=GetPutDiskObject(DiskObject,WorkbenchMessage->sm_ArgList[0].wa_Name);
  1745.     }
  1746.   else
  1747.     {
  1748.       char ProgramName[256];
  1749.  
  1750.       GetProgramName(ProgramName,sizeof(ProgramName));
  1751.       OldCurrentDir=CurrentDir(GetProgramDir());
  1752.       DiskObject=GetPutDiskObject(DiskObject,FilePart(ProgramName));
  1753.     }
  1754.   CurrentDir(OldCurrentDir);
  1755.   return DiskObject;
  1756. }
  1757.  
  1758. /************************************************************************/
  1759.  
  1760. static INLINE void ReconstructGame(void)
  1761.  
  1762. {
  1763.   if (display.window!=NULL)
  1764.     {
  1765.       KeyDown(KEY_PAUSE);
  1766.       KeyUp(KEY_PAUSE);
  1767.       if (MiscState.GameMode)
  1768.     {
  1769.       RedrawGame();
  1770.     }
  1771.     }
  1772. }
  1773.  
  1774. /************************************************************************/
  1775. /*                                    */
  1776. /* Compare tooltype                            */
  1777. /*                                    */
  1778. /************************************************************************/
  1779.  
  1780. static int CompareTooltype(const char *ToolType, const char *Name)
  1781.  
  1782. {
  1783.   int Parenthesis;
  1784.  
  1785.   while (*ToolType==' ')
  1786.     {
  1787.       ToolType++;
  1788.     }
  1789.   if ((Parenthesis=(*ToolType=='(')))
  1790.     {
  1791.       while (*(++ToolType)==' ')
  1792.     ;
  1793.     }
  1794.   while (*Name!='\0')
  1795.     {
  1796.       if (toupper(*ToolType)!=toupper(*Name))
  1797.     {
  1798.       return FALSE;
  1799.     }
  1800.       Name++;
  1801.       ToolType++;
  1802.     }
  1803.   return (*ToolType=='\0' || *ToolType==' ' || *ToolType=='=' || (Parenthesis && *ToolType==')'));
  1804. }
  1805.  
  1806. /************************************************************************/
  1807. /*                                    */
  1808. /* Free the new tooltype array                        */
  1809. /*                                    */
  1810. /************************************************************************/
  1811.  
  1812. static void FreeTooltypes(char **ToolTypes)
  1813.  
  1814. {
  1815.   char **ToolType;
  1816.  
  1817.   for (ToolType=ToolTypes; *ToolType; ToolType++)
  1818.     {
  1819.       int i;
  1820.  
  1821.       for (i=0; i<ARRAYSIZE(MrisToolTypes); i++)
  1822.     {
  1823.       if (CompareTooltype(*ToolType,MrisToolTypes[i]))
  1824.         {
  1825.           GS_MemoryFree(*ToolType);
  1826.         }
  1827.     }
  1828.     }
  1829.   GS_MemoryFree(ToolTypes);
  1830. }
  1831.  
  1832. /************************************************************************/
  1833. /*                                    */
  1834. /* Create new tooltype array                        */
  1835. /*                                    */
  1836. /************************************************************************/
  1837.  
  1838. static char **CreateTooltypes(char **ToolTypes)
  1839.  
  1840. {
  1841.   ULONG Count;
  1842.   char **ToolType;
  1843.   char **NewToolTypes;
  1844.  
  1845.   Count=0;
  1846.   if (ToolTypes!=NULL)
  1847.     {
  1848.       for (ToolType=ToolTypes; *ToolType!=NULL; ToolType++)
  1849.     {
  1850.       int i;
  1851.  
  1852.       Count++;
  1853.       for (i=0; i<ARRAYSIZE(MrisToolTypes); i++)
  1854.         {
  1855.           if (CompareTooltype(*ToolType,MrisToolTypes[i]))
  1856.         {
  1857.           Count--;
  1858.           break;
  1859.         }
  1860.         }
  1861.     }
  1862.     }
  1863.   if ((NewToolTypes=GS_MemoryAlloc(sizeof(char *)*(Count+ARRAYSIZE(MrisToolTypes)+1)))!=NULL)
  1864.     {
  1865.       char **NewToolType;
  1866.       int Error;
  1867.       int i;
  1868.  
  1869.       NewToolType=NewToolTypes;
  1870.       Error=FALSE;
  1871.  
  1872.       for (i=0; !Error && i<ARRAYSIZE(MrisToolTypes); i++)
  1873.     {
  1874.       char *Params[2];
  1875.  
  1876.       Params[0]=MrisToolTypes[i];
  1877.       switch (i)
  1878.         {
  1879.         case 8:
  1880.           Params[1]=(((struct MenuItem *)FindMenu(MSG_CONFIG_RANDOM_MENU))->Flags & CHECKED) ? "YES" : "NO";
  1881.           *NewToolType=GS_FormatString("%s=%s",Params,NULL,NULL);
  1882.           break;
  1883.  
  1884.         case 9:
  1885.           Params[1]=(((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_DYNAMIC_MENU))->Flags & CHECKED) ? "YES" : "NO";
  1886.           *NewToolType=GS_FormatString("%s=%s",Params,NULL,NULL);
  1887.           break;
  1888.  
  1889.         case 10:
  1890.           if (scoring.UserName[0]=='\0')
  1891.         {
  1892.           Params[1]="<user name>";
  1893.           *NewToolType=GS_FormatString("(%s=%s)",Params,NULL,NULL);
  1894.         }
  1895.           else
  1896.         {
  1897.           Params[1]=scoring.UserName;
  1898.           *NewToolType=GS_FormatString("%s=%s",Params,NULL,NULL);
  1899.         }
  1900.           break;
  1901.  
  1902.         case 11:
  1903.           Params[1]="<public screen name>";
  1904.           *NewToolType=GS_FormatString("(%s=%s)",Params,NULL,NULL);
  1905.           break;
  1906.  
  1907.         case 12:
  1908.           if (ScreenDescription==NULL)
  1909.         {
  1910.           Params[1]="";
  1911.         }
  1912.           else
  1913.         {
  1914.           Params[1]=ScreenDescription;
  1915.         }
  1916.           *NewToolType=GS_FormatString("%s=%s",Params,NULL,NULL);
  1917.           break;
  1918.  
  1919.         case 13:
  1920.           Params[1]=(((struct MenuItem *)FindMenu(MSG_CONFIG_CONTROL_JOYSTICK_MENU))->Flags & CHECKED) ? "YES" : "NO";
  1921.           *NewToolType=GS_FormatString("%s=%s",Params,NULL,NULL);
  1922.           break;
  1923.  
  1924.         case 14:
  1925.           if (TextAttr.ta_Name!=NULL)
  1926.         {
  1927.           *NewToolType=GS_FormatString("FONT=%s SIZE %u",&TextAttr,NULL,NULL);
  1928.         }
  1929.           else
  1930.         {
  1931.           Params[1]="<font description>";
  1932.           *NewToolType=GS_FormatString("(%s=%s)",Params,NULL,NULL);
  1933.         }
  1934.           break;
  1935.  
  1936.         case 15:
  1937.           Params[1]=(((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_MSIT_MENU))->Flags & CHECKED) ? "YES" : "NO";
  1938.           *NewToolType=GS_FormatString("%s=%s",Params,NULL,NULL);
  1939.           break;
  1940.  
  1941.         default:
  1942.           assert(i<KEYS);
  1943.           if (data.keysyms[i].Description!=GetString(MSG_KEY_UP+i))
  1944.         {
  1945.           Params[1]=data.keysyms[i].Description;
  1946.           *NewToolType=GS_FormatString("%s=%s",Params,NULL,NULL);
  1947.         }
  1948.           else
  1949.         {
  1950.           Params[1]="<key description>";
  1951.           *NewToolType=GS_FormatString("(%s=%s)",Params,NULL,NULL);
  1952.         }
  1953.           break;
  1954.         }
  1955.       if (*NewToolType==NULL)
  1956.         {
  1957.           Error=TRUE;
  1958.         }
  1959.       else
  1960.         {
  1961.           NewToolType++;
  1962.         }
  1963.     }
  1964.       if (!Error)
  1965.     {
  1966.       if (ToolTypes!=NULL)
  1967.         {
  1968.           for (ToolType=ToolTypes; *ToolType!=NULL; ToolType++)
  1969.         {
  1970.           for (i=0; i<ARRAYSIZE(MrisToolTypes) && !CompareTooltype(*ToolType,MrisToolTypes[i]); i++)
  1971.             ;
  1972.           if (i==ARRAYSIZE(MrisToolTypes))
  1973.             {
  1974.               *(NewToolType++)=*ToolType;
  1975.             }
  1976.         }
  1977.         }
  1978.       *NewToolType=NULL;
  1979.     }
  1980.       else
  1981.     {
  1982.       FreeTooltypes(NewToolTypes);
  1983.       NewToolTypes=NULL;
  1984.     }
  1985.     }
  1986.   return NewToolTypes;
  1987. }
  1988.  
  1989. /************************************************************************/
  1990. /*                                    */
  1991. /* Save current config as default                    */
  1992. /*                                    */
  1993. /************************************************************************/
  1994.  
  1995. static INLINE void SaveDefaultConfig(void)
  1996.  
  1997. {
  1998.   struct DiskObject *DiskObject;
  1999.  
  2000.   if ((DiskObject=DoDefaultIcon(NULL))!=NULL)
  2001.     {
  2002.       char **OldToolTypes;
  2003.  
  2004.       OldToolTypes=DiskObject->do_ToolTypes;
  2005.       if ((DiskObject->do_ToolTypes=CreateTooltypes(OldToolTypes))!=NULL)
  2006.     {
  2007.       UBYTE OldType;
  2008.       char *OldDefaultTool;
  2009.       struct DrawerData *OldDrawerData;
  2010.       char *OldToolWindow;
  2011.  
  2012.       OldType=DiskObject->do_Type;
  2013.       OldDefaultTool=DiskObject->do_DefaultTool;
  2014.       OldDrawerData=DiskObject->do_DrawerData;
  2015.       OldToolWindow=DiskObject->do_ToolWindow;
  2016.  
  2017.       DiskObject->do_Type=WBTOOL;
  2018.       DiskObject->do_DefaultTool=NULL;
  2019.       DiskObject->do_DrawerData=NULL;
  2020.       DiskObject->do_ToolWindow=NULL;
  2021.       DiskObject->do_StackSize=StackSize+2000;
  2022.  
  2023.       DoDefaultIcon(DiskObject);
  2024.  
  2025.       DiskObject->do_Type=OldType;
  2026.       DiskObject->do_DefaultTool=OldDefaultTool;
  2027.       DiskObject->do_DrawerData=OldDrawerData;
  2028.       DiskObject->do_ToolWindow=OldToolWindow;
  2029.       FreeTooltypes(DiskObject->do_ToolTypes);
  2030.     }
  2031.       DiskObject->do_ToolTypes=OldToolTypes;
  2032.       if (DiskObject!=&mrisIcon)
  2033.     {
  2034.       FreeDiskObject(DiskObject);
  2035.     }
  2036.     }
  2037. }
  2038.  
  2039. /************************************************************************/
  2040. /*                                    */
  2041. /* Put up the filerequester to save the configuration            */
  2042. /*                                    */
  2043. /************************************************************************/
  2044.  
  2045. static INLINE void OpenSaveConfig(void)
  2046.  
  2047. {
  2048.   if (ConfigMessage.Requester==NULL)
  2049.     {
  2050.       if ((AslBase=OpenLibrary((char *)AslName,0))!=NULL)
  2051.     {
  2052.       static struct TagItem TagList[]=
  2053.         {
  2054.           {ASLFR_InitialPattern, (ULONG)"#?.info"},
  2055.           {ASLFR_Flags1, FRF_DOSAVEMODE | FRF_DOPATTERNS},
  2056.           {TAG_DONE}
  2057.         };
  2058.  
  2059.       ConfigMessage.Message.mn_ReplyPort=&MiscPort;
  2060.       ConfigMessage.Requester=AllocAslRequestTags(ASL_FileRequest,
  2061.                               ASLFR_Screen, display.Screen->Screen,
  2062.                               ASLFR_Locale, Locale,
  2063.                               ASLFR_TitleText, GetString(MSG_SAVEREQUESTER_TITLE),
  2064.                               TAG_MORE, TagList);
  2065.       if (ConfigMessage.Requester==NULL)
  2066.         {
  2067.           CloseLibrary(AslBase);
  2068.         }
  2069.     }
  2070.       else
  2071.     {
  2072.       DisplayError(MSG_NO_LIBRARY,AslName);
  2073.     }
  2074.     }
  2075.   if (ConfigMessage.Message.mn_Node.ln_Type==NT_UNKNOWN && ConfigMessage.Requester!=NULL)
  2076.     {
  2077.       if (WorkbenchMessage!=NULL && WorkbenchMessage->sm_NumArgs>0)
  2078.     {
  2079.       BPTR OldCurrentDir;
  2080.  
  2081.       OldCurrentDir=CurrentDir(WorkbenchMessage->sm_ArgList[0].wa_Lock);
  2082.       AsyncAslRequest(&ConfigMessage);
  2083.       CurrentDir(OldCurrentDir);
  2084.     }
  2085.       else
  2086.     {
  2087.             AsyncAslRequest(&ConfigMessage);
  2088.     }
  2089.     }
  2090. }
  2091.  
  2092. /************************************************************************/
  2093. /*                                    */
  2094. /* Check whether an icon is really our own program icon.        */
  2095. /* "Name" must not have an ".info" suffix                */
  2096. /*                                    */
  2097. /************************************************************************/
  2098.  
  2099. static INLINE int CheckProgramIcon(BPTR DirLock, const char *Name)
  2100.  
  2101. {
  2102.   if (WorkbenchMessage!=NULL)
  2103.     {
  2104.       if (SameLock(DirLock,WorkbenchMessage->sm_ArgList[0].wa_Lock)==LOCK_SAME)
  2105.     {
  2106.       if (stricmp(Name,WorkbenchMessage->sm_ArgList[0].wa_Name)==0)
  2107.         {
  2108.           return TRUE;
  2109.         }
  2110.     }
  2111.     }
  2112.   else
  2113.     {
  2114.       if (SameLock(DirLock,GetProgramDir())==LOCK_SAME)
  2115.     {
  2116.       char ProgramName[256];
  2117.  
  2118.       GetProgramName(ProgramName,sizeof(ProgramName));
  2119.       if (stricmp(Name,FilePart(ProgramName))==0)
  2120.         {
  2121.           return TRUE;
  2122.         }
  2123.     }
  2124.     }
  2125.   return FALSE;
  2126. }
  2127.  
  2128. /************************************************************************/
  2129. /*                                    */
  2130. /* Do the save configuration                        */
  2131. /*                                    */
  2132. /************************************************************************/
  2133.  
  2134. static INLINE void SaveConfig(void)
  2135.  
  2136. {
  2137.   if (ConfigMessage.Result)
  2138.     {
  2139.       BPTR DirLock;
  2140.  
  2141.       if ((DirLock=Lock(((struct FileRequester *)ConfigMessage.Requester)->fr_Drawer,SHARED_LOCK))!=MKBADDR(NULL))
  2142.     {
  2143.       char *Name;
  2144.       LONG NameLength;
  2145.  
  2146.       Name=((struct FileRequester *)ConfigMessage.Requester)->fr_File;
  2147.       NameLength=strlen(Name);
  2148.       if (NameLength>5 && stricmp(&Name[NameLength-5],".info")==0)
  2149.         {
  2150.           Name[NameLength-5]='\0';
  2151.           NameLength=-NameLength;
  2152.         }
  2153.       if (!CheckProgramIcon(DirLock,Name))
  2154.         {
  2155.           struct DiskObject *DiskObject;
  2156.  
  2157.           DirLock=CurrentDir(DirLock);
  2158.           if ((DiskObject=GetDiskObject(Name))==NULL)
  2159.         {
  2160.           if (IoErr()==ERROR_OBJECT_NOT_FOUND)
  2161.             {
  2162.               DiskObject=DoDefaultIcon(NULL);
  2163.             }
  2164.         }
  2165.           if (DiskObject!=NULL)
  2166.         {
  2167.           char **OldToolTypes;
  2168.  
  2169.           OldToolTypes=DiskObject->do_ToolTypes;
  2170.           if ((DiskObject->do_ToolTypes=CreateTooltypes(OldToolTypes))!=NULL)
  2171.             {
  2172.               char *MrisPath;
  2173.  
  2174.               if ((MrisPath=GS_MemoryAlloc(1024))!=NULL)
  2175.             {
  2176.               if (NameFromLock(GetProgramDir(),MrisPath,1024))
  2177.                 {
  2178.                   if (WorkbenchMessage!=NULL)
  2179.                 {
  2180.                   assert(WorkbenchMessage->sm_NumArgs>0);
  2181.                   if (!AddPart(MrisPath,WorkbenchMessage->sm_ArgList[0].wa_Name,1024))
  2182.                     {
  2183.                       GS_MemoryFree(MrisPath);
  2184.                       MrisPath=NULL;
  2185.                     }
  2186.                 }
  2187.                   else
  2188.                 {
  2189.                   char ProgramName[256];
  2190.  
  2191.                   GetProgramName(ProgramName,sizeof(ProgramName));
  2192.                   if (!AddPart(MrisPath,FilePart(ProgramName),1024))
  2193.                     {
  2194.                       GS_MemoryFree(MrisPath);
  2195.                       MrisPath=NULL;
  2196.                     }
  2197.                 }
  2198.                 }
  2199.               else
  2200.                 {
  2201.                   GS_MemoryFree(MrisPath);
  2202.                   MrisPath=NULL;
  2203.                 }
  2204.             }
  2205.               if (MrisPath!=NULL)
  2206.             {
  2207.               UBYTE OldType;
  2208.               char *OldDefaultTool;
  2209.               struct DrawerData *OldDrawerData;
  2210.               char *OldToolWindow;
  2211.  
  2212.               OldType=DiskObject->do_Type;
  2213.               OldDefaultTool=DiskObject->do_DefaultTool;
  2214.               OldDrawerData=DiskObject->do_DrawerData;
  2215.               OldToolWindow=DiskObject->do_ToolWindow;
  2216.  
  2217.               DiskObject->do_Type=WBPROJECT;
  2218.               DiskObject->do_DefaultTool=MrisPath;
  2219.               DiskObject->do_DrawerData=NULL;
  2220.               DiskObject->do_ToolWindow=NULL;
  2221.               DiskObject->do_StackSize=StackSize+2000;
  2222.  
  2223.               if (!PutDiskObject(Name,DiskObject))
  2224.                 {
  2225.                   char String[ERRORSTRING_LENGTH];
  2226.  
  2227.                   DisplayError(MSG_PUTICON_ERROR,Name,ErrorString(String,IoErr()));
  2228.                 }
  2229.  
  2230.               DiskObject->do_Type=OldType;
  2231.               DiskObject->do_DefaultTool=OldDefaultTool;
  2232.               DiskObject->do_DrawerData=OldDrawerData;
  2233.               DiskObject->do_ToolWindow=OldToolWindow;
  2234.  
  2235.               GS_MemoryFree(MrisPath);
  2236.             }
  2237.               FreeTooltypes(DiskObject->do_ToolTypes);
  2238.             }
  2239.           DiskObject->do_ToolTypes=OldToolTypes;
  2240.           if (DiskObject!=&mrisIcon)
  2241.             {
  2242.               FreeDiskObject(DiskObject);
  2243.             }
  2244.         }
  2245.           DirLock=CurrentDir(DirLock);
  2246.         }
  2247.       else
  2248.         {
  2249.           SaveDefaultConfig();
  2250.         }
  2251.       if (NameLength<0)
  2252.         {
  2253.           Name[(-NameLength)-5]='.';
  2254.         }
  2255.       UnLock(DirLock);
  2256.     }
  2257.     }
  2258.   FreeAslRequest(ConfigMessage.Requester);
  2259.   ConfigMessage.Requester=NULL;
  2260.   CloseLibrary(AslBase);
  2261.   ConfigMessage.Message.mn_Node.ln_Type=NT_UNKNOWN;
  2262. }
  2263.  
  2264. /************************************************************************/
  2265. /*                                    */
  2266. /* Process window messages                        */
  2267. /*                                    */
  2268. /************************************************************************/
  2269.  
  2270. static int ProcessWindow(void)
  2271.  
  2272. {
  2273.   struct IntuiMessage *Message;
  2274.  
  2275.   if ((Message=(struct IntuiMessage *)GetMsg(&WindowPort))!=NULL)
  2276.     {
  2277.       if (Message->IDCMPWindow==display.window)
  2278.     {
  2279.       switch (Message->Class)
  2280.         {
  2281.         case IDCMP_GADGETUP:
  2282.           if ((struct Gadget *)Message->IAddress==&IconifyGadget)
  2283.         {
  2284.           KeyDown(KEY_ICONIZE);
  2285.         }
  2286.           break;
  2287.  
  2288.         case IDCMP_CLOSEWINDOW:
  2289.           global.quit=TRUE;
  2290.           break;
  2291.  
  2292.         case IDCMP_REFRESHWINDOW:
  2293.           BeginRefresh(display.window);
  2294.           refresh_window();
  2295.           EndRefresh(display.window,TRUE);
  2296.           break;
  2297.  
  2298.         case IDCMP_RAWKEY:
  2299.           HandleKey(Message);
  2300.           break;
  2301.  
  2302.         case IDCMP_ACTIVEWINDOW:
  2303.           if (((struct MenuItem *)FindMenu(MSG_CONFIG_CONTROL_JOYSTICK_MENU))->Flags & CHECKED)
  2304.         {
  2305.           AllocateJoystickCounter=JOYSTICK_TRIES;
  2306.         }
  2307.           break;
  2308.  
  2309.         case IDCMP_INACTIVEWINDOW:
  2310.           InactiveWindow();
  2311.           break;
  2312.  
  2313.         case IDCMP_MENUPICK:
  2314.           {
  2315.         UWORD Selection;
  2316.         int Modified;
  2317.  
  2318.         Modified=FALSE;
  2319.         Selection=Message->Code;
  2320.         while (Selection!=MENUNULL && !global.quit && Sprites!=NULL)
  2321.           {
  2322.             struct MenuItem *Item;
  2323.             UWORD UserData;
  2324.  
  2325.             Item=ItemAddress(display.Menustrip,Selection);
  2326.             UserData=((ULONG)GTMENUITEM_USERDATA(Item))&0xffff;
  2327.             switch (UserData)
  2328.               {
  2329.               case MSG_GAME_ABOUT_MENU:
  2330.             if (About==NULL)
  2331.               {
  2332.                 About=CreateMessage(GetString(MSG_ABOUT_TITLE),
  2333.                         GetString(MSG_ABOUT_BODY),
  2334.                         PROGRAM_VERSION " (" PROGRAM_DATE ")",
  2335.                         GetString(MSG_BROKER_TITLE),
  2336.                         GetString(MSG_GAME_DESCRIPTION),
  2337.                         GetString(MSG_COPYRIGHT1),
  2338.                         GetString(MSG_COPYRIGHT2),
  2339.                         GetString(MSG_COPYRIGHT3),
  2340.                         data.gender ? PROGRAM_MSIT : PROGRAM_MRIS,
  2341.                         display.dynamic ? GetString(MSG_DISPLAYINFO_DYNAMIC) : "",
  2342.                         Sprites->Colors.DistinctColors,
  2343.                         Sprites->Colors.ColorCount);
  2344.               }
  2345.             break;
  2346.  
  2347.               case MSG_CONFIG_DISPLAY_FONT_MENU:
  2348.             OpenConfigFont();
  2349.             break;
  2350.  
  2351.               case MSG_CONFIG_DISPLAY_SCREEN_MENU:
  2352.             OpenConfigScreen();
  2353.             break;
  2354.  
  2355.               case MSG_CONFIG_CONTROL_KEYS_MENU:
  2356.             OpenConfigKeysWindow();
  2357.             break;
  2358.  
  2359.               case MSG_CONFIG_RANDOM_MENU:
  2360.             if (!MiscState.GameMode)
  2361.               {
  2362.                 data.random=(Item->Flags & CHECKED) ? TRUE : FALSE;
  2363.               }
  2364.             break;
  2365.  
  2366.               case MSG_GAME_USER_MENU:
  2367.             OpenChangeUserWindow();
  2368.             break;
  2369.  
  2370.               case MSG_GAME_ERRORS_MENU:
  2371.             OpenErrorWindow();
  2372.             break;
  2373.  
  2374.               case MSG_GAME_QUIT_MENU:
  2375.             global.quit=TRUE;
  2376.             break;
  2377.  
  2378.               case MSG_CONFIG_DISPLAY_DYNAMIC_MENU:
  2379.             Modified|=ChangeDynamic(Item);
  2380.             break;
  2381.  
  2382.               case MSG_CONFIG_CONTROL_JOYSTICK_MENU:
  2383.             ChangeJoystick(Item);
  2384.             break;
  2385.  
  2386.               case MSG_CONFIG_DISPLAY_MSIT_MENU:
  2387.             Modified|=ChangeGender(Item);
  2388.             break;
  2389.  
  2390.               case MSG_GARDENS_MENU:
  2391.             Modified|=LoadBoards();
  2392.             break;
  2393.  
  2394.               case MSG_CONFIG_SAVEDEFAULT_MENU:
  2395.             SaveDefaultConfig();
  2396.             break;
  2397.  
  2398.               case MSG_CONFIG_SAVE_MENU:
  2399.             OpenSaveConfig();
  2400.             break;
  2401.  
  2402.               default:
  2403.             if (UserData>MSG_DEMO_MENU && UserData<=MSG_DEMO_SPRITES_MENU)
  2404.               {
  2405.                 MiscState.JumpDemo=UserData-MSG_DEMO_MENU;
  2406.                 Modified=TRUE;
  2407.               }
  2408.             break;
  2409.               }
  2410.             Selection=Item->NextSelect;
  2411.           }
  2412.         if (!global.quit && Modified)
  2413.           {
  2414.             ReconstructGame();
  2415.           }
  2416.           }
  2417.           break;
  2418.         }
  2419.       ReplyMsg(&Message->ExecMessage);
  2420.     }
  2421.       else if (Message->IDCMPWindow==ConfigKeysWindow)
  2422.     {
  2423.       ProcessConfigKeysWindow(Message);
  2424.     }
  2425.       else if (Message->IDCMPWindow==ChangeUserWindow)
  2426.     {
  2427.       ProcessChangeUserWindow(Message);
  2428.     }
  2429.       else
  2430.     {
  2431.       assert(Message->IDCMPWindow==ErrorWindow);
  2432.       ProcessErrorWindow(Message);
  2433.     }
  2434.       return TRUE;
  2435.     }
  2436.   return FALSE;
  2437. }
  2438.  
  2439. /************************************************************************/
  2440. /*                                    */
  2441. /* This is the main "game" loop while we're iconified            */
  2442. /*                                    */
  2443. /************************************************************************/
  2444.  
  2445. static INLINE void HandleIconified(void)
  2446.  
  2447. {
  2448.   struct DiskObject *DiskObject;
  2449.   struct AppIcon *AppIcon;
  2450.  
  2451. #ifdef DEBUG
  2452.   DiskObject=NULL;
  2453. #endif
  2454.   SetSignal(0,SIGBREAKF_CTRL_F);
  2455.   if ((WorkbenchBase=OpenLibrary("workbench.library",37))!=NULL)
  2456.     {
  2457.       if ((DiskObject=DoDefaultIcon(NULL))==NULL)
  2458.     {
  2459.       DiskObject=&mrisIcon;
  2460.     }
  2461.       DiskObject->do_CurrentX=NO_ICON_POSITION;
  2462.       DiskObject->do_CurrentY=NO_ICON_POSITION;
  2463.       AppIcon=AddAppIconA(0,0,"mris",&WBPort,NULL,DiskObject,NULL);
  2464.     }
  2465.   while (!global.quit && display.window==NULL)
  2466.     {
  2467.       ULONG Signals;
  2468.  
  2469.       Signals=Wait(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F | (1<<MiscPort.mp_SigBit));
  2470.       if (Signals & SIGBREAKF_CTRL_C)
  2471.     {
  2472.       global.quit=TRUE;
  2473.     }
  2474.       else if (Signals & SIGBREAKF_CTRL_F)
  2475.     {
  2476.       OpenGUI();
  2477.       ReconstructGame();
  2478.     }
  2479.       while (ProcessMisc())
  2480.     ;
  2481.       while (ProcessWindow())
  2482.     ;
  2483.     }
  2484.   if (WorkbenchBase!=NULL)
  2485.     {
  2486.       if (AppIcon!=NULL)
  2487.     {
  2488.       struct Message *Message;
  2489.  
  2490.       RemoveAppIcon(AppIcon);
  2491.       while ((Message=GetMsg(&WBPort))!=NULL)
  2492.         {
  2493.           ReplyMsg(Message);
  2494.         }
  2495.     }
  2496.       if (DiskObject!=&mrisIcon)    /* DiskObject _is_ initialized */
  2497.     {
  2498.       FreeDiskObject(DiskObject);
  2499.     }
  2500.       CloseLibrary(WorkbenchBase);
  2501.     }
  2502. }
  2503.  
  2504. /************************************************************************/
  2505. /*                                    */
  2506. /* Process a message from MiscPort                    */
  2507. /*                                    */
  2508. /************************************************************************/
  2509.  
  2510. static int ProcessMisc(void)
  2511.  
  2512. {
  2513.   struct Message *Message;
  2514.  
  2515.   if ((Message=GetMsg(&MiscPort))!=NULL)
  2516.     {
  2517.       if (Message==&GameSupportBase->Joystick.Request.io_Message)
  2518.     {
  2519.       HandleJoystick();
  2520.     }
  2521.       else if (Message==&FontMessage.Message)
  2522.     {
  2523.       if (ProcessConfigFont())
  2524.         {
  2525.           ReconstructGame();
  2526.         }
  2527.     }
  2528.       else if (Message==&ConfigMessage.Message)
  2529.     {
  2530.       SaveConfig();
  2531.     }
  2532.       else if (Message==&ScreenMessage.Message)
  2533.     {
  2534.       if (ProcessConfigScreen())
  2535.         {
  2536.           ErrorFlag=FALSE;
  2537.           CloseGUI();
  2538.           if (display.Screen!=NULL)
  2539.         {
  2540.           FreeScreen(display.Screen,TRUE);
  2541.           display.Screen=NULL;
  2542.         }
  2543.           OpenGUI();
  2544.           ReconstructGame();
  2545.         }
  2546.     }
  2547.       else /* CxMessage */
  2548.     {
  2549.       if (CxMsgType((CxMsg *)Message)==CXM_COMMAND)
  2550.         {
  2551.           switch (CxMsgID((CxMsg *)Message))
  2552.         {
  2553.         case CXCMD_APPEAR:
  2554.           if (display.window==NULL)
  2555.             {
  2556.               SetSignal(SIGBREAKF_CTRL_F,SIGBREAKF_CTRL_F);
  2557.             }
  2558.           else
  2559.             {
  2560.               ShowWindow(display.window);
  2561.             }
  2562.           break;
  2563.  
  2564.         case CXCMD_DISAPPEAR:
  2565.           if (display.window!=NULL)
  2566.             {
  2567.               KeyDown(KEY_ICONIZE);
  2568.             }
  2569.           break;
  2570.  
  2571.         case CXCMD_KILL:
  2572.           SetSignal(SIGBREAKF_CTRL_C,SIGBREAKF_CTRL_C);
  2573.           break;
  2574.         }
  2575.         }
  2576.       ReplyMsg(Message);
  2577.     }
  2578.       return TRUE;
  2579.     }
  2580.   return FALSE;
  2581. }
  2582.  
  2583. /************************************************************************/
  2584. /*                                    */
  2585. /* This is the main game loop                        */
  2586. /*                                    */
  2587. /************************************************************************/
  2588.  
  2589. static INLINE void Game(void)
  2590.  
  2591. {
  2592.   PROTOANIMATE((*animate));
  2593.  
  2594.   timer_open();
  2595.   animate = animate_demo;
  2596.   while(!global.quit)
  2597.     {
  2598.       if (display.window!=NULL)
  2599.     {
  2600.       int DoMessages;
  2601.  
  2602.       HandleMessageWindow(&CompileInfo);
  2603.       HandleMessageWindow(&About);
  2604.       color_cycle();
  2605.       if (CheckSignal(SIGBREAKF_CTRL_C))
  2606.         {
  2607.           global.quit=TRUE;
  2608.         }
  2609.       DoMessages=TRUE;
  2610.       while (!global.quit && display.window!=NULL && DoMessages)
  2611.         {
  2612.           DoMessages=ProcessMisc();
  2613.  
  2614.           /* process IDCMP message */
  2615.           if (ProcessWindow())
  2616.         {
  2617.           DoMessages=TRUE;
  2618.         }
  2619.  
  2620.           /* process Manual message */
  2621.           if (ProcessManual())
  2622.         {
  2623.           DoMessages=TRUE;
  2624.         }
  2625.         }
  2626.       if (display.window!=NULL && !global.quit)
  2627.         {
  2628.           if (AllocateJoystickCounter>0)
  2629.         {
  2630.           if (GS_AllocateJoystick(&MiscPort,GPCT_ABSJOYSTICK))
  2631.             {
  2632.               AllocateJoystickCounter=0;
  2633.               MiscState.Joystick=TRUE;
  2634.               GS_SendJoystick();
  2635.             }
  2636.           else
  2637.             {
  2638.               AllocateJoystickCounter--;
  2639.             }
  2640.         }
  2641.           if (MiscState.GameMode && !MiscState.GamePause && !MiscState.HappyBlanker)
  2642.         {
  2643.           if (GS_HappyBlanker())
  2644.             {
  2645.               MiscState.HappyBlanker=TRUE;
  2646.             }
  2647.         }
  2648.           if(global.pressed & (1 << KEY_THROW))
  2649.         {
  2650.           if(global.throw == 0)
  2651.             global.throw = 1;
  2652.         }
  2653.           else if(global.throw == 2)
  2654.         global.throw = 0;
  2655.           if(global.pressed & 1 << KEY_ICONIZE)
  2656.         {
  2657.           KeyDown(KEY_PAUSE);
  2658.           InactiveWindow();
  2659.           CloseGUI();
  2660.         }
  2661.           else
  2662.         {
  2663.           assert(animate != (PROTOANIMATE((*)))NULL);
  2664.           animate = (PROTOANIMATE((*)))(*animate)((PROTOVOID(*))NULL);
  2665.           show_updates();
  2666.           timer_wait();
  2667.           assert(monster.normals < 20);
  2668.         }
  2669.         }
  2670.     }
  2671.       else
  2672.     {
  2673.       HandleIconified();
  2674.     }
  2675.     }
  2676.   if (MiscState.GameMode)
  2677.     {
  2678.       StopGame();
  2679.     }
  2680.   FreeJoystick();
  2681.   timer_close();
  2682. }
  2683.  
  2684. /************************************************************************/
  2685.  
  2686. struct Menu *CreateMenustrip(struct NewMenu *NewMenu)
  2687.  
  2688. {
  2689.   unsigned int i;
  2690.  
  2691.   for (i=0; NewMenu[i].nm_Type!=NM_END; i++)
  2692.     {
  2693.       if ((ULONG)NewMenu[i].nm_Label<1024)
  2694.     {
  2695.       char *Item;
  2696.  
  2697.       Item=GetString((LONG)NewMenu[i].nm_Label);
  2698.       if (Item[0]!='\0')
  2699.         {
  2700.           NewMenu[i].nm_CommKey=Item;
  2701.         }
  2702.       NewMenu[i].nm_Label=Item+1;
  2703.     }
  2704.     }
  2705.   return CreateMenusA(NewMenu,NULL);
  2706. }
  2707.  
  2708. /************************************************************************/
  2709.  
  2710. static INLINE void MyCreateMenustrip(void)
  2711.  
  2712. {
  2713.   struct Menu *Menu;
  2714.   UWORD MenuNum;
  2715.  
  2716.   if ((display.Menustrip=CreateMenustrip(NewMenu))==NULL)
  2717.     {
  2718.       CloseAll(RETURN_ERROR,ERROR_NO_FREE_STORE);
  2719.     }
  2720.   for (Menu=display.Menustrip, MenuNum=0; Menu!=NULL; Menu=Menu->NextMenu, MenuNum++)
  2721.     {
  2722.       struct MenuItem *Item;
  2723.       UWORD ItemNum;
  2724.  
  2725.       GTMENU_USERDATA(Menu)=(APTR)(((ULONG)GTMENU_USERDATA(Menu))|(FULLMENUNUM(MenuNum,NOITEM,NOSUB)<<16));
  2726.       for (Item=Menu->FirstItem, ItemNum=0; Item!=NULL; Item=Item->NextItem, ItemNum++)
  2727.     {
  2728.       GTMENUITEM_USERDATA(Item)=(APTR)(((ULONG)GTMENUITEM_USERDATA(Item))|(FULLMENUNUM(MenuNum,ItemNum,NOSUB)<<16));
  2729.     }
  2730.     }
  2731. }
  2732.  
  2733. /************************************************************************/
  2734.  
  2735. static INLINE void InitKeys(void)
  2736.  
  2737. {
  2738.   int Key;
  2739.  
  2740.   for (Key=0; Key<ARRAYSIZE(data.keysyms); Key++)
  2741.     {
  2742.       ChangeKey(Key,NULL);
  2743.     }
  2744. }
  2745.  
  2746. /************************************************************************/
  2747. /*                                    */
  2748. /* Locate a menu item                            */
  2749. /*                                    */
  2750. /************************************************************************/
  2751.  
  2752. void *FindMenu(UWORD UserData)
  2753.  
  2754. {
  2755.   struct Menu *Menu;
  2756.  
  2757.   for (Menu=display.Menustrip; Menu!=NULL; Menu=Menu->NextMenu)
  2758.     {
  2759.       struct MenuItem *Item;
  2760.  
  2761.       if ((((ULONG)GTMENU_USERDATA(Menu))&0xffff)==UserData)
  2762.     {
  2763.       return Menu;
  2764.     }
  2765.       for (Item=Menu->FirstItem; Item!=NULL; Item=Item->NextItem)
  2766.     {
  2767.       struct MenuItem *SubItem;
  2768.  
  2769.       if ((((ULONG)GTMENUITEM_USERDATA(Item))&0xffff)==UserData)
  2770.         {
  2771.           return Item;
  2772.         }
  2773.       for (SubItem=Item->SubItem; SubItem!=NULL; SubItem=SubItem->NextItem)
  2774.         {
  2775.           if ((((ULONG)GTMENUITEM_USERDATA(SubItem))&0xffff)==UserData)
  2776.         {
  2777.           return SubItem;
  2778.         }
  2779.         }
  2780.     }
  2781.     }
  2782.   return NULL;
  2783. }
  2784.  
  2785. /************************************************************************/
  2786. /*                                    */
  2787. /* Determine default username                        */
  2788. /*                                    */
  2789. /************************************************************************/
  2790.  
  2791. static INLINE void InitUser(void)
  2792.  
  2793. {
  2794.   static const char * const UserVariables[]={"USER","USERNAME","REALNAME"};
  2795.  
  2796.   int i;
  2797.  
  2798.   for (i=ARRAYSIZE(UserVariables)-1;
  2799.        i>=0 && GetVar(UserVariables[i],scoring.UserName,sizeof(scoring.UserName),0)<5;
  2800.        i--)
  2801.     ;
  2802.   if (i<0)
  2803.     {
  2804.       scoring.UserName[0]='\0';
  2805.     }
  2806. }
  2807.  
  2808. /************************************************************************/
  2809. /*                                    */
  2810. /* As usual, Commodore didn't properly design their localization    */
  2811. /* facilities. Mris requires two strings which are country, not        */
  2812. /* language dependent (time formats). Since we only have catalogs,    */
  2813. /* I decided to put these strings into the catalog (although this is    */
  2814. /* not correct). But then, CatComp complains about the % formatting    */
  2815. /* commands...                                */
  2816. /* Therefore we use '\1' instead of %, and fix the strings in memory.    */
  2817. /*                                    */
  2818. /************************************************************************/
  2819.  
  2820. static char *RepairFormatString(LONG StringID)
  2821.  
  2822. {
  2823.   char *String;
  2824.   char *t;
  2825.  
  2826.   String=GetString(StringID);
  2827.   for (t=String; *t!='\0'; t++)
  2828.     {
  2829.       if (*t=='\1')
  2830.     {
  2831.       *t='%';
  2832.     }
  2833.     }
  2834.   return String;
  2835. }
  2836.  
  2837. /************************************************************************/
  2838.  
  2839. static INLINE void Init(void)
  2840.  
  2841. {
  2842.   BPTR OldCurrentDir;
  2843.  
  2844.   MiscPort.mp_SigBit=WindowPort.mp_SigBit=AllocSignal(-1);
  2845.   if ((GadToolsBase=OpenLibrary("gadtools.library",ROM_VERSION))==NULL)
  2846.     {
  2847.       MyExit(RETURN_CATASTROPHY,0);
  2848.     }
  2849.   if ((DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",ROM_VERSION))==NULL ||
  2850.       (IconBase=OpenLibrary("icon.library",ROM_VERSION))==NULL)
  2851.     {
  2852.       CloseAll(RETURN_FAIL,0);
  2853.     }
  2854.   OldCurrentDir=CurrentDir(GetProgramDir());
  2855.   GameSupportBase=(struct GameSupportBase *)OpenLibrary("gamesupport.library",0);
  2856.   CurrentDir(OldCurrentDir);
  2857.   CloseLibrary(&DOSBase->dl_lib);
  2858.   if (GameSupportBase==NULL)
  2859.     {
  2860.       CloseAll(RETURN_FAIL,0);
  2861.     }
  2862.   DOSBase=GameSupportBase->DOSBase;
  2863.   IntuitionBase=GameSupportBase->IntuitionBase;
  2864.   GfxBase=GameSupportBase->GfxBase;
  2865.   UtilityBase=GameSupportBase->UtilityBase;
  2866.   LayersBase=GameSupportBase->LayersBase;
  2867.   KeymapBase=GameSupportBase->KeymapBase;
  2868.   if ((CxBase=OpenLibrary("commodities.library",37))==NULL)
  2869.     {
  2870.       CloseAll(RETURN_FAIL,0);
  2871.     }
  2872.   if ((LocaleBase=GameSupportBase->LocaleBase)!=NULL)
  2873.     {
  2874.       static struct TagItem CatalogTags[]=
  2875.     {
  2876.       {OC_BuiltInLanguage, (ULONG)"deutsch"},
  2877.       {OC_Version, 1},
  2878.       {TAG_DONE}
  2879.     };
  2880.  
  2881.       Locale=OpenLocale(NULL);
  2882.       if ((Catalog=OpenCatalogA(Locale,PROGRAM_NAME ".catalog",CatalogTags))==NULL)
  2883.     {
  2884.       LONG Error;
  2885.  
  2886.       if ((Error=IoErr())!=0)
  2887.         {
  2888.           CloseAll(RETURN_FAIL,Error);
  2889.         }
  2890.     }
  2891.     }
  2892.   Formats.ElapsedTime=RepairFormatString(MSG_ELAPSED_TIME_FORMAT);
  2893.   Formats.DateTime=RepairFormatString(MSG_DATE_FORMAT);
  2894. #if !defined(__SASC)
  2895.   if ((DitherPattern=AllocMem(2*sizeof(UWORD),MEMF_CHIP))==NULL)
  2896.     {
  2897.       CloseAll(RETURN_FAIL,ERROR_NO_FREE_STORE);
  2898.     }
  2899.   DitherPattern[0]=0x5555;
  2900.   DitherPattern[1]=0xaaaa;
  2901. #endif
  2902.   scoring.mine.Score.Name=scoring.UserName;
  2903.   scoring.display=-1;
  2904.   WBPort.mp_SigTask=MiscPort.mp_SigTask=WindowPort.mp_SigTask=FindTask(NULL);
  2905. }
  2906.  
  2907. /************************************************************************/
  2908.  
  2909. void StartGame(void)
  2910.  
  2911. {
  2912.   struct Menu *Menu;
  2913.   struct MenuItem *Item;
  2914.  
  2915.   Item=(struct MenuItem *)FindMenu(MSG_CONFIG_RANDOM_MENU);
  2916.   OffMenu(display.window,((ULONG)GTMENUITEM_USERDATA(Item))>>16);
  2917.   data.random=(Item->Flags & CHECKED) ? TRUE : FALSE;
  2918.   Menu=(struct Menu *)FindMenu(MSG_GARDENS_MENU);
  2919.   OffMenu(display.window,((ULONG)GTMENU_USERDATA(Menu))>>16);
  2920.   Menu=(struct Menu *)FindMenu(MSG_DEMO_MENU);
  2921.   OffMenu(display.window,((ULONG)GTMENU_USERDATA(Menu))>>16);
  2922.   MiscState.GameMode=TRUE;
  2923.   MiscState.JumpDemo=0;
  2924.   MiscState.GamePause=FALSE;
  2925.   LoadBoards();
  2926. }
  2927.  
  2928. /************************************************************************/
  2929.  
  2930. void StopGame(void)
  2931.  
  2932. {
  2933.   if (MiscState.HappyBlanker)
  2934.     {
  2935.       MiscState.HappyBlanker=FALSE;
  2936.       GS_NoHappyBlanker();
  2937.     }
  2938.   history.msec += global.msec;
  2939.   scoring.mine.score = global.score;
  2940.   scoring.mine.screen = global.screen;
  2941.   scoring.mine.elapsed = (unsigned)(history.msec / 1000);
  2942.   if (scoring.ScoreHandle==NULL && board.boards>0)
  2943.     {
  2944.       scoring.ScoreHandle=GS_ObtainScoreHandle(&ScoreDef.ScoreDef,board.Name,scoring.UserName);
  2945.     }
  2946.   if (scoring.ScoreHandle!=NULL && scoring.mine.score>=SCORE_THRESHOLD)
  2947.     {
  2948.       GS_InsertScore(scoring.ScoreHandle,&scoring.mine.Score);
  2949.     }
  2950.   else
  2951.     {
  2952.       ULONG Micros;
  2953.  
  2954.       CurrentTime(&scoring.mine.Score.TimeStamp,&Micros);
  2955.     }
  2956.   EnableMenu(MSG_DEMO_MENU,FALSE);
  2957.   EnableMenu(MSG_GARDENS_MENU,FALSE);
  2958.   EnableMenu(MSG_CONFIG_RANDOM_MENU,TRUE);
  2959.   MiscState.GameMode=FALSE;
  2960.   MiscState.GamePause=FALSE;
  2961. }
  2962.  
  2963. /************************************************************************/
  2964. /*                                    */
  2965. /* Read garden directory, and create initial "Gardens" menu        */
  2966. /*                                    */
  2967. /************************************************************************/
  2968.  
  2969. static INLINE void InitGardens(void)
  2970.  
  2971. {
  2972.   LONG Error;
  2973.  
  2974.   if ((GardenDir=Lock("PROGDIR:mris gardens",SHARED_LOCK))!=MKBADDR(NULL))
  2975.     {
  2976.       struct ExAllControl *ExAllControl;
  2977.       BPTR OldCurrentDir;
  2978.  
  2979.       OldCurrentDir=CurrentDir(GardenDir);
  2980.       if ((ExAllControl=AllocDosObject(DOS_EXALLCONTROL,NULL))!=NULL)
  2981.     {
  2982.       void *ExAllData;
  2983.  
  2984.       if ((ExAllData=GS_MemoryAlloc(4096))!=NULL)
  2985.         {
  2986.           BOOL More;
  2987.  
  2988.           Error=0;
  2989.           ExAllControl->eac_LastKey=0;
  2990.           ExAllControl->eac_MatchString=NULL;
  2991.           ExAllControl->eac_MatchFunc=NULL;
  2992.           do
  2993.         {
  2994.           More=ExAll(GardenDir,ExAllData,4096,ED_SIZE,ExAllControl);
  2995.           if (!More)
  2996.             {
  2997.               LONG Err;
  2998.  
  2999.               if ((Err=IoErr())!=ERROR_NO_MORE_ENTRIES)
  3000.             {
  3001.               if (Error==0)
  3002.                 {
  3003.                   Error=Err;
  3004.                 }
  3005.               break;
  3006.             }
  3007.             }
  3008.           if (ExAllControl->eac_Entries>0)
  3009.             {
  3010.               struct ExAllData *Data;
  3011.  
  3012.               for (Data=ExAllData; Data!=NULL; Data=Data->ed_Next)
  3013.             {
  3014.               if ((Data->ed_Size>=12+sizeof(BOARD)) && ((Data->ed_Size-12)%sizeof(BOARD))==0)
  3015.                 {
  3016.                   BPTR Filehandle;
  3017.  
  3018.                   if ((Filehandle=Open(Data->ed_Name,MODE_OLDFILE))!=MKBADDR(NULL))
  3019.                 {
  3020.                   char Header[12];
  3021.  
  3022.                   if (Read(Filehandle,Header,12)==12)
  3023.                     {
  3024.                       if (strncmp(Header,"mris Garden!",12)==0)
  3025.                     {
  3026.                       struct StringNode *Name;
  3027.  
  3028.                       if ((Name=GS_MemoryAlloc(sizeof(struct StringNode)+strlen(Data->ed_Name)+1+1))!=NULL)
  3029.                         {
  3030.                           struct StringNode **Current;
  3031.  
  3032.                           strcpy(((char *)(Name+1))+1,Data->ed_Name);
  3033.                           for (Current=&GardenStrings;
  3034.                            *Current!=NULL && (Locale!=NULL ?
  3035.                                       StrnCmp(Locale,Data->ed_Name,
  3036.                                           ((char *)((*Current)+1))+1,
  3037.                                           -1,SC_COLLATE2) :
  3038.                                       Stricmp(Data->ed_Name,
  3039.                                           ((char *)((*Current)+1))+1))>0;
  3040.                            Current=&(*Current)->Next)
  3041.                         ;
  3042.                           Name->Next=*Current;
  3043.                           *Current=Name;
  3044.                         }
  3045.                       else
  3046.                         {
  3047.                           Error=ERROR_NO_FREE_STORE;
  3048.                         }
  3049.                     }
  3050.                     }
  3051.                   Close(Filehandle);
  3052.                 }
  3053.                 }
  3054.             }
  3055.             }
  3056.         }
  3057.           while (More);
  3058.           if (Error==ERROR_NO_MORE_ENTRIES)
  3059.         {
  3060.           Error=0;
  3061.         }
  3062.           GS_MemoryFree(ExAllData);
  3063.           if (Error==0)
  3064.         {
  3065.           struct StringNode *Name;
  3066.           struct MenuItem **Item;
  3067.           ULONG Count;
  3068.  
  3069.           Count=0;
  3070.           Item=&((struct Menu *)FindMenu(MSG_GARDENS_MENU))->FirstItem;
  3071.           for (Name=GardenStrings; Error==0 && Name!=NULL; Name=Name->Next)
  3072.             {
  3073.               struct NewMenu NewMenu[2];
  3074.  
  3075.               NewMenu[0].nm_Type=NM_ITEM;
  3076.               if (Count<10)
  3077.             {
  3078.               NewMenu[0].nm_CommKey=(char *)(Name+1);
  3079.               *(char *)(Name+1)=Count==9 ? '0' : '1'+Count;
  3080.             }
  3081.               else
  3082.             {
  3083.               NewMenu[0].nm_CommKey=NULL;
  3084.             }
  3085.               NewMenu[0].nm_Label=((char *)(Name+1))+1;
  3086.               NewMenu[0].nm_Flags=(stricmp(NewMenu[0].nm_Label,"Digits")==0) ? CHECKIT|CHECKED : CHECKIT;
  3087.               NewMenu[0].nm_MutualExclude=~(1<<Count++);
  3088.               NewMenu[0].nm_UserData=(APTR)MSG_GARDENS_MENU;
  3089.               NewMenu[1].nm_Type=NM_END;
  3090.               if ((*Item=(struct MenuItem *)CreateMenusA(NewMenu,NULL))!=NULL)
  3091.             {
  3092.               Item=&(*Item)->NextItem;
  3093.             }
  3094.               else
  3095.             {
  3096.               Error=ERROR_NO_FREE_STORE;
  3097.             }
  3098.             }
  3099.         }
  3100.         }
  3101.       else
  3102.         {
  3103.           Error=ERROR_NO_FREE_STORE;
  3104.         }
  3105.       FreeDosObject(DOS_EXALLCONTROL,ExAllControl);
  3106.     }
  3107.       else
  3108.     {
  3109.       Error=ERROR_NO_FREE_STORE;
  3110.     }
  3111.       CurrentDir(OldCurrentDir);
  3112.       if (Error==0)
  3113.     {
  3114.       LoadBoards();
  3115.       UpdateWindowTitle();
  3116.     }
  3117.     }
  3118.   else
  3119.     {
  3120.       Error=IoErr();
  3121.     }
  3122.   if (Error!=0)
  3123.     {
  3124.       CloseAll(RETURN_FAIL,Error);
  3125.     }
  3126. }
  3127.  
  3128. /************************************************************************/
  3129. /*                                    */
  3130. /* Process a YES/NO tooltype.                        */
  3131. /*                                    */
  3132. /************************************************************************/
  3133.  
  3134. static void ProcessBoolean(char **ToolTypes, char *Name, UWORD MenuID)
  3135.  
  3136. {
  3137.   char *ToolType;
  3138.  
  3139.   if ((ToolType=FindToolType(ToolTypes,Name))!=NULL)
  3140.     {
  3141.       struct MenuItem *Item;
  3142.  
  3143.       Item=FindMenu(MenuID);
  3144.       if (MatchToolValue(ToolType,"YES"))
  3145.     {
  3146.       Item->Flags|=CHECKED;
  3147.     }
  3148.       else if (MatchToolValue(ToolType,"NO"))
  3149.     {
  3150.       Item->Flags&=~CHECKED;
  3151.     }
  3152.       else
  3153.     {
  3154.       while (*ToolType==' ' || *ToolType=='\t')
  3155.         {
  3156.           ToolType++;
  3157.         }
  3158.       if (ToolType=='\0')
  3159.         {
  3160.           Item->Flags|=CHECKED;
  3161.         }
  3162.       else
  3163.         {
  3164.           DisplayError(MSG_BOOLTOOLTYPE_ERROR,ToolType,Name);
  3165.         }
  3166.     }
  3167.     }
  3168. }
  3169.  
  3170. /************************************************************************/
  3171. /*                                    */
  3172. /* Process a tooltype array.                        */
  3173. /*                                    */
  3174. /************************************************************************/
  3175.  
  3176. static void ProcessToolTypes(char **ToolTypes)
  3177.  
  3178. {
  3179.   char *ToolType;
  3180.   int Key;
  3181.  
  3182.   ProcessBoolean(ToolTypes,MrisToolTypes[8],MSG_CONFIG_RANDOM_MENU);
  3183.   ProcessBoolean(ToolTypes,MrisToolTypes[9],MSG_CONFIG_DISPLAY_DYNAMIC_MENU);
  3184.   ProcessBoolean(ToolTypes,MrisToolTypes[13],MSG_CONFIG_CONTROL_JOYSTICK_MENU);
  3185.   ProcessBoolean(ToolTypes,MrisToolTypes[15],MSG_CONFIG_DISPLAY_MSIT_MENU);
  3186.  
  3187.   for (Key=0; Key<KEYS; Key++)
  3188.     {
  3189.       if ((ToolType=FindToolType(ToolTypes,MrisToolTypes[Key]))!=NULL)
  3190.     {
  3191.       ChangeKey(Key,ToolType);
  3192.     }
  3193.     }
  3194.  
  3195.   if ((ToolType=FindToolType(ToolTypes,MrisToolTypes[10]))!=NULL)
  3196.     {
  3197.       while (*ToolType==' ')
  3198.     {
  3199.       ToolType++;
  3200.     }
  3201.       strncpy(scoring.UserName,ToolType,sizeof(scoring.UserName)-1);
  3202.       scoring.UserName[sizeof(scoring.UserName)-1]='\0';
  3203.     }
  3204.  
  3205.   if ((ToolType=FindToolType(ToolTypes,MrisToolTypes[11]))!=NULL)
  3206.     {
  3207.       while (*ToolType==' ')
  3208.     {
  3209.       ToolType++;
  3210.     }
  3211.       GS_MemoryFree(ScreenDescription);
  3212.       if (*ToolType=='\0')
  3213.     {
  3214.       ScreenDescription=NULL;
  3215.     }
  3216.       else
  3217.     {
  3218.       if ((ScreenDescription=GS_FormatString("PUBSCREEN \"%s\"",&ToolType,NULL,NULL))==NULL)
  3219.         {
  3220.           DisplayError(0,ERROR_NO_FREE_STORE);
  3221.         }
  3222.     }
  3223.     }
  3224.  
  3225.   if ((ToolType=FindToolType(ToolTypes,MrisToolTypes[12]))!=NULL)
  3226.     {
  3227.       while (*ToolType==' ')
  3228.     {
  3229.       ToolType++;
  3230.     }
  3231.       GS_MemoryFree(ScreenDescription);
  3232.       if ((ScreenDescription=GS_MemoryAlloc(strlen(ToolType)+1))!=NULL)
  3233.     {
  3234.       strcpy(ScreenDescription,ToolType);
  3235.     }
  3236.       else
  3237.     {
  3238.       DisplayError(0,ERROR_NO_FREE_STORE);
  3239.     }
  3240.     }
  3241.  
  3242.   if ((ToolType=FindToolType(ToolTypes,MrisToolTypes[14]))!=NULL)
  3243.     {
  3244.       LONG Error;
  3245.       struct TextAttr NewTextAttr;
  3246.  
  3247.       if ((Error=MakeTextAttr(ToolType,&NewTextAttr))==0)
  3248.     {
  3249.       if (NewTextAttr.ta_YSize<CELL_HEIGHT)
  3250.         {
  3251.           FreeVec(TextAttr.ta_Name);
  3252.           TextAttr.ta_Name=NewTextAttr.ta_Name;
  3253.           TextAttr.ta_YSize=NewTextAttr.ta_YSize;
  3254.         }
  3255.       else
  3256.         {
  3257.           FreeVec(NewTextAttr.ta_Name);
  3258.         }
  3259.     }
  3260.       else
  3261.     {
  3262.       char String[ERRORSTRING_LENGTH];
  3263.  
  3264.       DisplayError(MSG_FONTDESC_ERROR,ToolType,ErrorString(String,IoErr()));
  3265.     }
  3266.     }
  3267. }
  3268.  
  3269. /************************************************************************/
  3270. /*                                    */
  3271. /* Check out our program name                        */
  3272. /*                                    */
  3273. /************************************************************************/
  3274.  
  3275. static INLINE void CheckName(void)
  3276.  
  3277. {
  3278.   const char *Name;
  3279.   char ProgramName[256];
  3280.  
  3281.   if (WorkbenchMessage==NULL)
  3282.     {
  3283.       GetProgramName(ProgramName,sizeof(ProgramName));
  3284.       Name=FilePart(ProgramName);
  3285.     }
  3286.   else
  3287.     {
  3288.       Name=FindTask(NULL)->tc_Node.ln_Name;
  3289.     }
  3290.   while (*Name!='\0')
  3291.     {
  3292.       if (strnicmp(Name,"msit",4)==0)
  3293.     {
  3294.       ((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_MSIT_MENU))->Flags|=CHECKED;
  3295.       break;
  3296.     }
  3297.       Name++;
  3298.     }
  3299. }
  3300.  
  3301. /************************************************************************/
  3302. /*                                    */
  3303. /* Get arguments                            */
  3304. /*                                    */
  3305. /************************************************************************/
  3306.  
  3307. static INLINE void ObtainArgs(void)
  3308.  
  3309. {
  3310.   CheckName();
  3311.   if (WorkbenchMessage==NULL)
  3312.     {
  3313.       struct DiskObject *DiskObject;
  3314.  
  3315.       if ((DiskObject=DoDefaultIcon(NULL))!=NULL)
  3316.     {
  3317.       struct
  3318.         {
  3319.           LONG Random;
  3320.           LONG NoRandom;
  3321.           LONG Dynamic;
  3322.           LONG NoDynamic;
  3323.           LONG Joystick;
  3324.           LONG NoJoystick;
  3325.           LONG mris;
  3326.           LONG msit;
  3327.           char *User;
  3328.           char *Pubscreen;
  3329.           char *Screen;
  3330.           char *Font;
  3331.           char *Keys[KEYS];
  3332.         } Arguments;
  3333.       struct RDArgs *RDArgs;
  3334.  
  3335.       ProcessToolTypes(DiskObject->do_ToolTypes);
  3336.       memset(&Arguments,0,sizeof(Arguments));
  3337.       if ((RDArgs=ReadArgs("RANDOM/S,NORANDOM/S,"
  3338.                    "DYNAMIC/S,NODYNAMIC/S,"
  3339.                    "JOYSTICK/S,NOJOYSTICK/S,"
  3340.                    "MRIS/S,MSIT/S,"
  3341.                    "USER=USERNAME/K,"
  3342.                    "PUBSCREEN/K,"
  3343.                    "SCREEN/K,"
  3344.                    "FONT/K,"
  3345.                    "UP/K,DOWN/K,LEFT/K,RIGHT/K,THROW/K,PAUSE/K,QUIT/K,ICONIZE/K",
  3346.                    (LONG *)&Arguments,NULL))!=NULL)
  3347.         {
  3348.           int Key;
  3349.  
  3350.           if (Arguments.Random)
  3351.         {
  3352.           ((struct MenuItem *)FindMenu(MSG_CONFIG_RANDOM_MENU))->Flags|=CHECKED;
  3353.         }
  3354.           if (Arguments.NoRandom)
  3355.         {
  3356.           ((struct MenuItem *)FindMenu(MSG_CONFIG_RANDOM_MENU))->Flags&=~CHECKED;
  3357.         }
  3358.           if (Arguments.Dynamic)
  3359.         {
  3360.           ((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_DYNAMIC_MENU))->Flags|=CHECKED;
  3361.         }
  3362.           if (Arguments.NoDynamic)
  3363.         {
  3364.           ((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_DYNAMIC_MENU))->Flags&=~CHECKED;
  3365.         }
  3366.           if (Arguments.Joystick)
  3367.         {
  3368.           ((struct MenuItem *)FindMenu(MSG_CONFIG_CONTROL_JOYSTICK_MENU))->Flags|=CHECKED;
  3369.         }
  3370.           if (Arguments.NoJoystick)
  3371.         {
  3372.           ((struct MenuItem *)FindMenu(MSG_CONFIG_CONTROL_JOYSTICK_MENU))->Flags&=~CHECKED;
  3373.         }
  3374.           if (Arguments.mris)
  3375.         {
  3376.           ((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_MSIT_MENU))->Flags&=~CHECKED;
  3377.         }
  3378.           if (Arguments.msit)
  3379.         {
  3380.           ((struct MenuItem *)FindMenu(MSG_CONFIG_DISPLAY_MSIT_MENU))->Flags|=CHECKED;
  3381.         }
  3382.           if (Arguments.User!=NULL)
  3383.         {
  3384.           strncpy(scoring.UserName,Arguments.User,sizeof(scoring.UserName)-1);
  3385.           scoring.UserName[sizeof(scoring.UserName)-1]='\0';
  3386.         }
  3387.           for (Key=0; Key<KEYS; Key++)
  3388.         {
  3389.           if (Arguments.Keys[Key]!=NULL)
  3390.             {
  3391.               if (Arguments.Keys[Key][0]=='\0')
  3392.             {
  3393.               ChangeKey(Key,NULL);
  3394.             }
  3395.               else
  3396.             {
  3397.               ChangeKey(Key,Arguments.Keys[Key]);
  3398.             }
  3399.             }
  3400.         }
  3401.           if (Arguments.Pubscreen!=NULL)
  3402.         {
  3403.           GS_MemoryFree(ScreenDescription);
  3404.           if (Arguments.Pubscreen[0]=='\0')
  3405.             {
  3406.               ScreenDescription=NULL;
  3407.             }
  3408.           else
  3409.             {
  3410.               if ((ScreenDescription=GS_FormatString("PUBSCREEN \"%s\"",&Arguments.Pubscreen,NULL,NULL))==NULL)
  3411.             {
  3412.               DisplayError(0,ERROR_NO_FREE_STORE);
  3413.             }
  3414.             }
  3415.         }
  3416.           if (Arguments.Screen!=NULL)
  3417.         {
  3418.           GS_MemoryFree(ScreenDescription);
  3419.           if ((ScreenDescription=GS_MemoryAlloc(strlen(Arguments.Screen)+1))!=NULL)
  3420.             {
  3421.               strcpy(ScreenDescription,Arguments.Screen);
  3422.             }
  3423.           else
  3424.             {
  3425.               DisplayError(0,ERROR_NO_FREE_STORE);
  3426.             }
  3427.         }
  3428.           if (Arguments.Font!=NULL)
  3429.         {
  3430.           struct TextAttr NewTextAttr;
  3431.           LONG Error;
  3432.  
  3433.           if ((Error=MakeTextAttr(Arguments.Font,&NewTextAttr))==0)
  3434.             {
  3435.               if (NewTextAttr.ta_YSize<CELL_HEIGHT)
  3436.             {
  3437.               FreeVec(TextAttr.ta_Name);
  3438.               TextAttr.ta_Name=NewTextAttr.ta_Name;
  3439.               TextAttr.ta_YSize=NewTextAttr.ta_YSize;
  3440.             }
  3441.               else
  3442.             {
  3443.               FreeVec(NewTextAttr.ta_Name);
  3444.             }
  3445.             }
  3446.           else
  3447.             {
  3448.               char String[ERRORSTRING_LENGTH];
  3449.  
  3450.               DisplayError(MSG_FONTDESC_ERROR,Arguments.Font,ErrorString(String,Error));
  3451.             }
  3452.         }
  3453.           FreeArgs(RDArgs);
  3454.         }
  3455.       else
  3456.         {
  3457.           char String[ERRORSTRING_LENGTH];
  3458.  
  3459.           DisplayError(MSG_COMMANDLINE_ERROR,ErrorString(String,IoErr()));
  3460.         }
  3461.       if (DiskObject!=&mrisIcon)
  3462.         {
  3463.           FreeDiskObject(DiskObject);
  3464.         }
  3465.     }
  3466.     }
  3467.   else
  3468.     {
  3469.       LONG Count;
  3470.  
  3471.       for (Count=0; Count<WorkbenchMessage->sm_NumArgs; Count++)
  3472.     {
  3473.       BPTR OldCurrentDir;
  3474.       char *Name;
  3475.       struct DiskObject *DiskObject;
  3476.       
  3477.       OldCurrentDir=CurrentDir(WorkbenchMessage->sm_ArgList[Count].wa_Lock);
  3478.       Name=WorkbenchMessage->sm_ArgList[Count].wa_Name;
  3479.       if ((DiskObject=GetDiskObject(Name))!=NULL)
  3480.         {
  3481.           ProcessToolTypes(DiskObject->do_ToolTypes);
  3482.           FreeDiskObject(DiskObject);
  3483.         }
  3484.       else
  3485.         {
  3486.           char String[ERRORSTRING_LENGTH];
  3487.           
  3488.           DisplayError(MSG_GETICON_ERROR,Name,ErrorString(String,IoErr()));
  3489.         }
  3490.       CurrentDir(OldCurrentDir);
  3491.     }
  3492.     }
  3493.   data.random=(((struct MenuItem *)FindMenu(MSG_CONFIG_RANDOM_MENU))->Flags & CHECKED) ? TRUE : FALSE;
  3494. }
  3495.  
  3496. /************************************************************************/
  3497.  
  3498. static INLINE void CreateBroker(void)
  3499.  
  3500. {
  3501.   LONG Error;
  3502.   ULONG Count;
  3503.  
  3504.   Count=0;
  3505.   NewBroker.nb_Title=GetString(MSG_BROKER_TITLE);
  3506.   NewBroker.nb_Descr=GetString(MSG_GAME_DESCRIPTION);
  3507.   do
  3508.     {
  3509.       GS_MemoryFree(NewBroker.nb_Name);
  3510.       if (Count==0)
  3511.     {
  3512.       NewBroker.nb_Name=GS_FormatString("mris",&Count,NULL,NULL);
  3513.     }
  3514.       else
  3515.     {
  3516.       NewBroker.nb_Name=GS_FormatString("mris.%lu",&Count,NULL,NULL);
  3517.     }
  3518.       if (NewBroker.nb_Name!=NULL)
  3519.     {
  3520.       if ((Broker=CxBroker(&NewBroker,&Error))==NULL)
  3521.         {
  3522.           Count++;
  3523.         }
  3524.     }
  3525.       else
  3526.     {
  3527.       Error=ERROR_NO_FREE_STORE;
  3528.     }
  3529.     }
  3530.   while (Error==CBERR_DUP);
  3531.   ActivateCxObj(Broker,TRUE);
  3532. }
  3533.  
  3534. /************************************************************************/
  3535.  
  3536. void AmigaMain(void)
  3537.  
  3538. {
  3539.   Init();
  3540.   MyCreateMenustrip();
  3541.   InitKeys();
  3542.   InitUser();
  3543.   ObtainArgs();
  3544.   InitGardens();
  3545.   CreateBroker();
  3546.   OpenGUI();
  3547.   Game();
  3548.   CloseAll(RETURN_OK,0);
  3549. }
  3550.